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 a Double
parece ser una fuente de confusión (especialmente porque estábamos acostumbrados a agregar nsec). Esa Double
sintaxis de "agregar segundos como " funciona porque deadline
es una DispatchTime
y, detrás de escena, hay un +
operador que tomará una Double
y agregará esa cantidad de segundos a DispatchTime
:
public func +(time: DispatchTime, seconds: Double) -> DispatchTime
Pero, si realmente desea agregar un número entero de mseg, μs o nsec a DispatchTime
, también puede agregar a DispatchTimeInterval
a a 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 de la DispatchTime
clase.
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, 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 [weak self]
lista de captura en el 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 encuentra la cancel()
llamada, el bloque finalizará su ejecución (a menos que esté verificando manualmente isCancelled
dentro del bloque).