www net international index homepage cfm biconline swift events

net - swift payment



¿Cancelar un evento cronometrado en Swift? (7)

Esto debería funcionar:

var doIt = true var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: Selector("doSomething"), userInfo: nil, repeats: false) //you have now 10 seconds to change the doIt variable to false, to not run THE CODE func doSomething() { if(doIt) { //THE CODE } timer.invalidate() }

Quiero ejecutar un bloque de código en 10 segundos desde un evento, pero quiero poder cancelarlo para que si algo sucede antes de esos 10 segundos, el código no se ejecutará después de que hayan pasado 10 segundos.

He estado usando esto, pero no se puede cancelar:

static func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure ) }

¿Cómo puedo lograr esto?


Por alguna razón, NSObject.cancelPreviousPerformRequests(withTarget: self) no funcionaba para mí. Un trabajo en el que pensé estaba dando con la cantidad máxima de bucles que permitiría y luego usando ese Int para controlar si incluso se llamó a la función.

Entonces puedo establecer el valor de currentLoop desde cualquier otro lugar en mi código y detiene el bucle.

//loopMax = 200 var currentLoop = 0 func loop() { if currentLoop == 200 { //do nothing. } else { //perform loop. //keep track of current loop count. self.currentLoop = self.currentLoop + 1 let deadline = DispatchTime.now() + .seconds(1) DispatchQueue.main.asyncAfter(deadline: deadline) { //enter custom loop parameters print("i looped") self.loop() } }

y luego en otra parte de tu código puedes

func stopLooping() { currentLoop = 199 //setting it to 199 allows for one last loop to happen. You can adjust based on the amount of loops you want to be able to do before it just stops. For instance you can set currentLoop to 195 and then implement a fade animation while loop is still happening a bit. }

Es realmente bastante dinámico en realidad. Por ejemplo, puede ver si currentLoop == 123456789, y se ejecutará infinitamente (más o menos) hasta que lo establezca en ese valor en otro lugar de su código. O puede establecerlo en String () o Bool () incluso, si sus necesidades no se basan en el tiempo como las mías.


Pruebe esto (Swift 2.x, consulte la respuesta de David a continuación para Swift 3):

typealias dispatch_cancelable_closure = (cancel : Bool) -> () func delay(time:NSTimeInterval, closure:()->()) -> dispatch_cancelable_closure? { func dispatch_later(clsr:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), clsr) } var closure:dispatch_block_t? = closure var cancelableClosure:dispatch_cancelable_closure? let delayedClosure:dispatch_cancelable_closure = { cancel in if let clsr = closure { if (cancel == false) { dispatch_async(dispatch_get_main_queue(), clsr); } } closure = nil cancelableClosure = nil } cancelableClosure = delayedClosure dispatch_later { if let delayedClosure = cancelableClosure { delayedClosure(cancel: false) } } return cancelableClosure; } func cancel_delay(closure:dispatch_cancelable_closure?) { if closure != nil { closure!(cancel: true) } } // usage let retVal = delay(2.0) { println("Later") } delay(1.0) { cancel_delay(retVal) }

Del comentario de Waam aquí: dispatch_after - GCD en rápido?


Swift 3 tiene DispatchWorkItem :

let task = DispatchWorkItem { print("do something") } // execute task in 2 seconds DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2, execute: task) // optional: cancel task task.cancel()


Usted necesita hacer ésto:

class WorkItem { private var pendingRequestWorkItem: DispatchWorkItem? func perform(after: TimeInterval, _ block: @escaping VoidBlock) { // Cancel the currently pending item pendingRequestWorkItem?.cancel() // Wrap our request in a work item let requestWorkItem = DispatchWorkItem(block: block) pendingRequestWorkItem = requestWorkItem DispatchQueue.main.asyncAfter(deadline: .now() + after, execute: requestWorkItem) } } // to use lazy var workItem = WorkItem() private func onMapIdle() { workItem.perform(after: 1.0) { self.handlePOIListingSearch() } }

Referencias

Enlace swiftbysundell

Link git


Utilizo el método de @sas en algunos proyectos, de alguna manera esto ya no funciona, tal vez algo cambió después de Swift 2.1.1. valor de copia en lugar de puntero?

El método más sencillo para mí es:

var canceled = false delay(0.25) { if !canceled { doSomething() } }


Actualización para Swift 3.0

Establecer selector de ejecución

perform(#selector(foo), with: nil, afterDelay: 2)

el método foo llamará después de 2 segundos

func foo() { //do something }

Para cancelar el método pendiente llame

NSObject.cancelPreviousPerformRequests(withTarget: self)