example dispatchqueue dispatch_async async ios swift swift4 swift3 grand-central-dispatch xcode8 swift5

ios - dispatchqueue - nsoperationqueue swift 3 example



¿Cómo escribo dispatch_after GCD en Swift 3, 4 y 5? (13)

En Swift 2, pude usar dispatch_after para retrasar una acción usando grand central dispatch:

var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))) dispatch_after(dispatchTime, dispatch_get_main_queue(), { // your function here })

Pero esto ya no parece compilarse desde Swift 3. ¿Cuál es la forma preferida de escribir esto en Swift moderno?


En Swift 4.1 y Xcode 9.4.1

La respuesta simple es ...

//To call function after 5 seconds time DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { //Here call your function }


Esto funcionó para mí en Swift 3

let time1 = 8.23 let time2 = 3.42 // Delay 2 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("Sum of times: /(time1 + time2)") }


La sintaxis es simplemente:

// to run something in 0.1 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // your code here }

Tenga en cuenta que la sintaxis anterior de agregar seconds como Double parece ser una fuente de confusión (especialmente porque estábamos acostumbrados a agregar nsec). Esa sintaxis de "agregar segundos como Double " funciona porque la deadline es un tiempo de DispatchTime y, detrás de escena, hay un operador + que tomará un Double y agregará tantos segundos al tiempo de DispatchTime :

public func +(time: DispatchTime, seconds: Double) -> DispatchTime

Pero, si realmente desea agregar un número entero de mseg, μs o nsec al DispatchTime , también puede agregar un DispatchTimeInterval a un DispatchTime . Eso significa que puedes hacer:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { os_log("500 msec seconds later") } DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) { os_log("1m μs seconds later") } DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) { os_log("1.5b nsec seconds later") }

Todo esto funciona a la perfección debido a este método de sobrecarga separado para el operador + en la clase DispatchTime .

public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime

Se le preguntó cómo se cancela una tarea despachada. Para hacer esto, use DispatchWorkItem . Por ejemplo, esto inicia una tarea que se activará en cinco segundos, o si el controlador de vista se descarta y se desasigna, su deinit cancelará la tarea:

class ViewController: UIViewController { private var item: DispatchWorkItem? override func viewDidLoad() { super.viewDidLoad() item = DispatchWorkItem { [weak self] in self?.doSomething() self?.item = nil } DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!) } deinit { item?.cancel() } func doSomething() { ... } }

Tenga en cuenta el uso de la lista de captura [weak self] en DispatchWorkItem . Esto es esencial para evitar un ciclo de referencia fuerte. También tenga en cuenta que esto no hace una cancelación preventiva, sino que simplemente detiene la tarea de comenzar si aún no lo ha hecho. Pero si ya ha comenzado cuando se encuentra con la llamada cancel() , el bloque finalizará su ejecución (a menos que esté verificando manualmente isCancelled dentro del bloque).


Ninguna de las respuestas mencionó ejecutarse en un hilo no principal, por lo que agregué mis 2 centavos.

En la cola principal (hilo principal)

let mainQueue = DispatchQueue.main let deadline = DispatchTime.now() + .seconds(10) mainQueue.asyncAfter(deadline: deadline) { // ... }

O

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) { // ... }

En cola global (subproceso no principal, basado en QOS especificado).

let backgroundQueue = DispatchQueue.global() let deadline = DispatchTime.now() + .milliseconds(100) backgroundQueue.asyncAfter(deadline: deadline, qos: .background) { // ... }

O

DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) { // ... }


Puedes usar

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) { // Code }


Si solo quieres la función de retraso en

Swift 4 y 5

func delay(interval: TimeInterval, closure: @escaping () -> Void) { DispatchQueue.main.asyncAfter(deadline: .now() + interval) { closure() } }

Puedes usarlo como:

delay(interval: 1) { print("Hi!") }


Un sabor algo diferente de la respuesta aceptada.

Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) + .microseconds(500) + .nanoseconds(1000)) { print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds + 1000 nanoseconds)") }


después del lanzamiento de Swift 3, también se debe agregar @escaping

func delay(_ delay: Double, closure: @escaping () -> ()) { DispatchQueue.main.asyncAfter(deadline: .now() + delay) { closure() } }


llame a DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)

Recomiendo encarecidamente utilizar las herramientas de Xcode para convertir a Swift 3 (Edición> Convertir> A sintaxis Swift actual). Esto me atrapó


prueba esto

let when = DispatchTime.now() + 1.5 DispatchQueue.main.asyncAfter(deadline: when) { //some code }


Swift 4

Puede crear una extensión en DispatchQueue y agregar un retraso de función que use la función DispatchQueue asyncAfter internamente

extension DispatchQueue { static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) { DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: closure) } }

y use

DispatchQueue.delay(.milliseconds(10)) { print("task to be done") }


Swift 4:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { // Code }

Por el momento, se pueden .seconds(Int) , .microseconds(Int) y .nanoseconds(Int) .


Swift 5 y superior

DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: { // code to execute })