thread grand dispatch_async central animate swift animation dispatch

swift - grand - Detener dispatch_after



swift thread (4)

Puede crear una variable boolean shouldCancelAnimation y probarla dentro del bloque dispatch_after para evitar la ejecución de su animación.

var shouldCancelAnimation = false // property of class func runAnimation() { let delay = 1.8 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue()) { if !self.shouldCancelAnimation { self.rain.alpha = 0 UIView.animateWithDuration(5, animations: { self.rain.alpha = 1 }) self.tip.startAnimating() } self.shouldCancelAnimation = false } } func viewWasTouched() // This could be touches began or taprecognizer event { shouldCancelAnimation = true }

Utilizo una animación para especificar un consejo para ayudar a la interacción con el retraso al usar estos:

let delay = 1.8 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue()) { //call the method which have the steps after delay. self.rain.alpha = 0 UIView.animateWithDuration(5, animations: { self.rain.alpha = 1 }) self.tip.startAnimating() }

Pero, necesito detener este proceso de demora si, antes de comenzar la animación, el usuario toca la pantalla.


Aquí hay una solución general que escribí para cancelar un dispatch_after en Swift:

typealias cancellable_closure = (() -> ())? func dispatch_after(#seconds:Double, queue: dispatch_queue_t = dispatch_get_main_queue(), closure:()->()) -> cancellable_closure { var cancelled = false let cancel_closure: cancellable_closure = { cancelled = true } dispatch_after( dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue, { if !cancelled { closure() } } ) return cancel_closure } func cancel_dispatch_after(cancel_closure: cancellable_closure) { cancel_closure?() }

Uso:

let doSomethingLater = dispatch_after(seconds: 3.0) { something() } .... if shouldCancelForSomeReason { cancel_dispatch_after(doSomethingLater) }

Por defecto, se ejecuta en la cola principal, pero puede pasar un parámetro para que se ejecute en otra cola:

let doSomethingLater = dispatch_after(seconds: 3.0, queue: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { something() }


iOS 8 y OS X Yosemite introdujeron dispatch_block_cancel que le permiten cancelarlos antes de que comiencen a ejecutarse

Usted declara una variable en clase de la siguiente manera:

var block: dispatch_block_t?

Inicia la variable del block y bríndalo en dispatch_after :

block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) { print("I executed") } let time: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(5 * NSEC_PER_SEC)) dispatch_after(time, dispatch_get_main_queue(), block!)

Después de eso, puedes cancelarlo de la siguiente manera:

dispatch_block_cancel(block!)


Swift 3.0 Ejemplo DispatchQueue cancelar o detener

var dispatchQueue: DispatchQueue? var dispatchWorkItem: DispatchWorkItem? func someOnClickButtonStart() { self.dispatchQueue = DispatchQueue.global(qos: .background) // create queue self.dispatchWorkItem = DispatchWorkItem { // create work item // async code goes here } if self.dispatchWorkItem != nil { self.dispatchQueue?.asyncAfter( deadline: .now() + .seconds(1), execute: self.dispatchWorkItem! ) // schedule work item } } func someOnClickButtonCancel() { if let dispatchWorkItem = self.dispatchWorkItem { dispatchWorkItem.cancel() // cancel work item } }