Cómo hacer multihilo, concurrencia o paralelismo en iOS Swift?


¿Hay alguna forma de crear un hilo de trabajo en Swift? por ejemplo, si hay una funcionalidad importante que requiere muchos cálculos y, por lo tanto, hace que el hilo principal se retrase durante unos segundos, si me gustaría mover esa funcionalidad a un hilo separado o a un hilo que no bloquee el hilo principal ¿hay alguna manera de hacerlo con Swift?

He revisado los componentes básicos y avanzados de la documentación de Apple para Swift, pero no hay nada sobre concurrencia o paralelismo, ¿alguien sabe algo sobre cómo hacerlo(si es posible)?

Author: Gabriel Southern, 2014-07-05

3 answers

O también puede usar colas de operación. En Swift 3:

let queue = OperationQueue()

queue.addOperation() {
    // do something in the background

    OperationQueue.main.addOperation() {
        // when done, update your UI and/or model on the main queue
    }
}

Ya sea esto, o GCD, que Andy ilustró, funcionan bien.

Vea la Guía de Programación de Concurrencia de Apple para los méritos relativos de las colas de operación y las colas de despacho (también conocido como Grand Central Dispatch, GCD). Si bien esa guía todavía ilustra los ejemplos que usan Objective-C, la API y los conceptos son básicamente los mismos en Swift (solo use la sintaxis Swift). La documentación para la DCG y las colas de operación en Xcode describen las API de Objective-C y Swift.


Por cierto, notarás que tanto en el ejemplo anterior como en la demostración de GCD de Andy, usamos "cierres finales". Por ejemplo, si nos fijamos en la definición addOperationWithBlock, que se define como una función con un parámetro que es un "cierre" (que es análogo a un bloque en Objective-C):

func addOperation(_ block: @escaping () -> Swift.Void)

Eso podría llevarte a suponer que lo invocarías de la siguiente manera:

queue.addOperation({
    // do something in the background
})

Pero cuando el último el parámetro de una función es un cierre, la sintaxis de cierre final le permite tomar ese parámetro de cierre final de los paréntesis de la función, y moverlo después de la función, produciendo:

queue.addOperation() {
    // do something in the background
}

Y debido a que no queda nada en los paréntesis, incluso puedes ir un paso más allá y eliminar esos paréntesis vacíos:

queue.addOperation {
    // do something in the background
}

Esperemos que eso ilustra cómo interpretar la NSOperationQueue/OperationQueue y / o declaraciones de funciones GCD y utilícelas en su código.

 45
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:07

Puede utilizar Grand Central Dispatch (GCD) para tales tareas.

Este es un ejemplo básico:

let backgroundQueue: dispatch_queue_t = dispatch_queue_create("com.a.identifier", DISPATCH_QUEUE_CONCURRENT)

// can be called as often as needed
dispatch_async(backgroundQueue) {
    // do calculations
}

// release queue when you are done with all the work
dispatch_release(backgroundQueue)
 17
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-05 19:18:13

Esta biblioteca le permite describir la concurrencia de una manera súper expresiva:

func handleError(_ error) { ... }

HoneyBee.start(on: DispatchQueue.main) { root in
    root.setErrorHandler(handleError)
        .chain(function1) // runs on main queue
        .setBlockPerformer(DispatchQueue.global())
        .chain(function2) // runs on background queue
        .branch { stem in
            stem.chain(func3) // runs in parallel with func4
            +
            stem.chain(func4) // runs in parallel with func3
        }
        .chain(func5) // runs after func3 and func4 have finished
        .setBlockPerformer(DispatchQueue.main)
        .chain(updateUIFunc)
}
 0
Author: Alex Lynch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-25 16:56:30