C'è un video WWDC (2012) che probabilmente ti aiuterà. Utilizza un numero personalizzato NSOperationQueue
e inserisce i blocchi asincroni all'interno di NSOperations
in modo da poter mantenere un handle sui blocchi e annullare i blocchi rimanenti in coda.
Un'idea sarebbe quella di avere la gestione degli errori dei blocchi figlio per chiamare un metodo sul thread principale nella classe che gestisce lo NSOperationQueue
. La classe potrebbe quindi cancellare il resto in modo appropriato. In questo modo il blocco figlio deve solo conoscere la propria discussione e il thread principale. Ecco un link al video
https://developer.apple.com/videos/wwdc/2012/
Il video si chiama "Costruire Interfacce utente simultanee su iOS". La parte rilevante è principalmente nella seconda parte, ma probabilmente vorrai vedere l'intera cosa nel suo contesto.
EDIT:
Se possibile, mi consiglia di maneggiare la risposta in un blocco incorporato che avvolge piacevolmente insieme, che è quello che penso che stai dopo ..
//Define an NSBlockOperation, and get weak reference to it
NSBlockOperation *blockOp = [[NSBlockOperation alloc]init];
__weak NSBlockOperation *weakBlockOp = blockOp;
//Define the block and add to the NSOperationQueue, when the view controller is popped
//we can call -[NSOperationQueue cancelAllOperations] which will cancel all pending threaded ops
[blockOp addExecutionBlock: ^{
//Once a block is executing, will need to put manual checks to see if cancel flag has been set otherwise
//the operation will not be cancelled. The check is rather pointless in this example, but if the
//block contained multiple lines of long running code it would make sense to do this at safe points
if (![weakBlockOp isCancelled]) {
//substitute code in here, possibly use *synchronous* NSURLConnection to get
//what you need. This code will block the thread until the server response
//completes. Hence not executing the following block and keeping it on the
//queue.
__block NSData *temp;
response = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
[operationQueue addOperationWithBlock:^{
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
//Call selector on main thread to handle canceling
//Main thread can then use handle on NSOperationQueue
//to cancel the rest of the blocks
});
else {
//Continue executing relevant code....
}
}];
}
}];
[operationQueue addOperation:blockOp];
fonte
2012-07-31 19:34:43
Grazie, ho guardato il video. Immagino che cosa stia inciampando su come un'operazione possa essere essenzialmente mantenuta in coda mentre è in attesa di una risposta asincrona ...? Sarebbe comodo essere in grado di sfruttare NSOperationQueue. Ho usato quella classe in altre app, ma in precedenza avevo solo la coda per gestire le richieste in uscita, non l'elaborazione della risposta. In questa app, l'operazione non viene eseguita finché non viene elaborata la risposta e vengono completate anche eventuali richieste secondarie associate. – xyzzycoder
puoi inserire il codice di gestione della risposta in un blocco incorporato? Aggiornerò la mia risposta –
Se ci si trova nel mondo 'NSOperation', piuttosto che in' dispatch_async (dispatch_get_main_queue(),^{}); ', perché no' [[NSOperationQueue mainQueue] addOperationWithBlock:^{}]; ' ? Quello che hai va bene, ma è strano mescolare le chiamate GCD con le chiamate 'NSOperationQueue'. – Rob