2015-01-22 8 views
24

C'è un modo per cancellare dispatch_after() programmato per un po 'di tempo in futuro, e non è stato sparato finora? Sto provando a creare qualcosa come uno scheduler per gli aggiornamenti dal server, e questo metodo è proprio come voglio, ma, mi piacerebbe cancellarlo e riprogrammarlo ad un certo punto. È possibile o devo effettuare il fallback e usare NSTimer?annulla il metodo dispatch_after()?

+0

sì. sembra che abbiamo duplicati. Mi chiedo se è possibile unire queste domande? –

risposta

1

Utilizzare una fonte di timer di invio (ovvero ciò che dispatch_after utilizza internamente in ogni caso).

Un'origine del timer di invio può essere annullata o i suoi parametri del timer modificati dopo la creazione.

19

Non esiste un modo per impedire l'esecuzione di dispatch_block una volta che è stato inviato alla coda, il che significa che il tuo dispatch_after non può essere annullato. L'unica opzione è aggiungere al blocco una condizione da verificare in fase di esecuzione per impedire l'esecuzione. ie.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(),^{ 
if(self.shouldExecuteDispatchBlock) 
{ // do your stuff } }); 
+0

Hmmm così fino alla prossima volta che si esegue l'esecuzione di questo blocco (ed è impostato per essere cancellato), immagino che fino ad allora si accaparrerebbe tutta la memoria/gli oggetti. Forse un problema se i tuoi cicli sono come 60 minuti? :-) – Jonny

+0

Sì e no. Il blocco copia la memoria, il che significa che se si fa riferimento a un valore int nel proprio blocco, questo verrà copiato e rimarrà in memoria come duplicato per tutto il tempo in cui il blocco è attivo. Ma per oggetto, non li duplica, copia l'indirizzo. Nel caso in cui si refere un'immagine, si avrà un oggetto UIImage nell'heap ma il blocco manterrà solo un valore del puntatore (8 byte in arc64) quindi, nessun problema. Ovviamente l'immagine verrà mantenuta in memoria fino a quando il blocco si spegne, quindi non sarà pulito da arco. –

+0

L'ho trasformato in un'estensione per DispatchQueue: https://github.com/nrbrook/DispatchAfterCancellable – Nick

11

OK, così, con tutte le risposte raccolte, e le possibili soluzioni, sembra la migliore per questo caso (conservando semplicità) sta chiamando performSelector:withObject:afterDelay: e annullarlo con cancelPreviousPerformRequestsWithTarget: chiamata quando desiderato. Nel mio caso - poco prima di pianificare chiamata successiva ritardata:

[NSObject cancelPreviousPerformRequestsWithTarget: self selector:@selector(myDelayedMethod) object: self]; 

[self performSelector:@selector(myDelayedMethod) withObject: self afterDelay: desiredDelay]; 
+0

Ho iniziato questo percorso, ma come farlo con i metodi di classe (che è il motivo per cui sono passato a 'dispatch_after')? – Olie

+0

@Olie bravo. Quindi devi avvolgere quelle chiamate in istanza, o usare dispatch + flag (indovina, in secondo luogo sarebbe più semplice) –

Problemi correlati