2009-04-18 2 views
9

Ho un NSInvocationOperation che scarica e analizza una serie di NSXMLDocuments in background alla mia interfaccia utente reattiva.Come fermare un NSInvocationOperation?

Il mio tentativo di interrompere l'operazione di chiamata è di chiamare cancellAllOperations del mio NSOperationQueue. Ma sembra che questo non fermerà l'esecuzione dell'invocazione.

Qualche idea su come risolvere questo problema?

risposta

3

Spetta all'implementazione dell'oggetto NSOperation in realtà stop cosa sta facendo, pulizia e uscita quando viene notificato che è stato cancellato. La messaggistica che si desidera annullare tutte le operazioni sulla coda farà sì che la coda smetta di eliminare le nuove operazioni da eseguire e invierà il messaggio di annullamento a tutte le operazioni attualmente in esecuzione.

Nel metodo principale dell'operazione, è necessario verificare isCancelled e gestire tale stato quando si è effettivamente annullato.

Per ulteriori informazioni, vedere Creating and Managing Operation Objects nella Guida alla programmazione del threading.

+0

Ma vedere le altre risposte, sembra che non sia possibile farlo (almeno nel modo standard di controllare 'isCancelled') quando si utilizza' NSInvocationOperation'. – jrdioko

5

Il post precedente è ottimo, ma per rispondere più direttamente alla domanda originale: sembra che non sia possibile interrompere l'oggetto NSInvocationOperation perché non supporta le cancellazioni. Dovrai creare una sottoclasse.

11

AGGIORNAMENTO: Gli strumenti dimostrano perdite abbondanti quando lo faccio. Procedere con attenzione! Sto mantenendo questo qui nel caso in cui io sia in realtà su qualcosa e qualcun altro può capire come superare l'ostacolo di perdita.

Ecco un'idea contorta, che sto cercando di ri-mentre scrivo questo:

impostare il funzionamento come il oggetto per NSInvocationOperation s' initWithTarget: selettore: oggetto: metodo. si dispone già di un Presumendo NSOperationQueue (che chiameremo coda):

NSInvocationOperation *operation = [NSInvocationOperation alloc]; 
operation = [operation initWithTarget:self selector:@selector(myOperation:) object:operation]; 
[queue addOperation:operation]; 
[operation release]; 

Nota che dobbiamo spezzare l'alloc nella propria chiamata. Altrimenti non possiamo impostare oggetto a operazione!

Quindi, all'interno del metodo di operazione, eseguire il cast dell'oggetto e spruzzare i controlli per isCancelled come desiderato. Per esempio:

- (void)myOperation:(id)object { 
    NSInvocationOperation *operation = (NSInvocationOperation *)object; 
    if ([operation isCancelled]) return; 
    ... 
    } 

Assicurarsi che il selettore si conclude con i due punti indietro nella initWithTarget: ... chiamata, in quanto sarete di passaggio in un oggetto ora.

Finora, tutto bene. Ora se riesco a forzare cancelAllOperations, saprò se funziona davvero. :)

+0

Non provarlo a causa di perdite. Ma l'idea è fantastica! –

8

È necessario verificare se NSInvocationOperation isCancelled è YES. farlo in NSInvocationOperation, è possibile utilizzare Chiave Valore Observing:

Aggiungi il tuo oggetto come NSInvocationOperation isCancelled osservatore durante l'esecuzione dell'operazione:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:<targetObj> selector:@selector(<targetMethod>) object:nil]; 
[operation addObserver:<targetObj> forKeyPath:@"isCancelled" options:NSKeyValueObservingOptionNew context:nil]; 
[operQueue addOperation:operation]; 
[operation release]; 

Poi nel targetObj attuare

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; 

a guardare per isCancelled modificato da NSOperationQueue's cancellAllOperations. Qui puoi impostare un flag privato e targetMethod può controllarlo e cancellarlo se necessario.