15

Sto spostando il mio codice dal normale GCD a NSOperationQueue perché ho bisogno di alcune delle funzionalità. Gran parte del mio codice si basa su dispatch_after per funzionare correttamente. C'è un modo per fare qualcosa di simile con uno NSOperation?dispatch_after equivalent in NSOperationQueue

Questo è parte del mio codice che deve essere convertito in NSOperation. Se potessi fornire un esempio di conversione usando questo codice, sarebbe fantastico.

dispatch_queue_t queue = dispatch_queue_create("com.cue.MainFade", NULL); 
dispatch_time_t mainPopTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeRun * NSEC_PER_SEC)); 
dispatch_after(mainPopTime, queue, ^(void){ 
    if(dFade !=nil){ 
     double incriment = ([dFade volume]/[self fadeOut])/10; //incriment per .1 seconds. 
     [self doDelayFadeOut:incriment with:dFade on:dispatch_queue_create("com.cue.MainFade", 0)]; 
    } 

}); 

risposta

22

NSOperationQueue non ha alcun meccanismo di temporizzazione in esso. Se è necessario impostare un ritardo come questo e quindi eseguire un'operazione, è necessario pianificare lo per gestire il ritardo e rendere il codice finale uno NSOperation.

NSOperation è progettato per gestire operazioni batch più o meno. Il caso d'uso è leggermente diverso da GCD e in effetti utilizza GCD su piattaforme con GCD.

Se il problema che si sta tentando di risolvere è ottenere una notifica del timer cancellabile, suggerirei di utilizzare NSTimer e invalidarlo se è necessario annullarlo. Quindi, in risposta al timer, è possibile eseguire il codice o utilizzare una coda di invio o NSOperationQueue.

3

È possibile continuare a utilizzare dispatch_after() con una coda globale, quindi pianificare l'operazione sulla coda di funzionamento. I blocchi passati a dispatch_after() non vengono eseguiti dopo il tempo specificato, vengono semplicemente pianificati dopo tale orario.

Qualcosa di simile:

dispatch_after 
(
    mainPopTime, 
    dispatch_get_main_queue(), 
    ^{ 
     [myOperationQueue addOperation:theOperationObject]; 
    } 
); 
1

È possibile eseguire un'NSOperazione che consente di dormire: MYDelayOperation. Quindi aggiungilo come dipendenza per la tua vera operazione di lavoro.

@interface MYDelayOperation : NSOperation 
... 
- (void)main 
{ 
    [NSThread sleepForTimeInterval:delay]; // delay is passed in constructor 
} 

Usage:

NSOperation *theOperationObject = ... 
MYDelayOperation *delayOp = [[MYDelayOperation alloc] initWithDelay:5]; 
[theOperationObject addDependency:delayOp]; 
[myOperationQueue addOperations:@[ delayOp, theOperationObject] waitUntilFinished:NO]; 
+1

Ciò manterrà l'operazione attiva nella coda, e in caso di una coda con un numero limitato di operazioni attive, che il sonno terrà altre operazioni ammissibili da esecuzione. – Bogdan

+2

Concordato con @Bogdan. Questo non è un buon approccio. Non si dovrebbe mai bloccare i thread della coda di operazioni. – Randy

0
[operationQueue performSelector:@selector(addOperation:) 
        withObject:operation 
        afterDelay:delay];