NSOperation est très utile. Pour l'utiliser, vous étendez NSOperation et remplacez la méthode "main". Dans la méthode principale, vous effectuez vos calculs/requêtes Web, etc. NSOperation est donc idéal pour les tâches que vous pouvez suivre en quelques étapes simples. Après chaque étape, vous testez si tout va bien et passez à l'étape suivante. Une fois cela fait, vous pouvez simplement instancier votre NSOperation personnalisé et le remettre à un objet NSOperationQueue et il s'occupera de l'enfilage, du démarrage, de l'arrêt du nettoyage etc.
Dans l'exemple ci-dessous, j'ai écrit un protocole à manipuler l'achèvement de la tâche, je vous conseille de prendre cette approche au lieu d'utiliser la notification - sauf si vous avez plusieurs objets qui doivent être notifiés instantanément.
Faire une nouvelle classe qui étend la classe NSOperation:
//This object takes a "searchTerm" and waits to be "started".
#import <Foundation/Foundation.h>
@protocol ISSearchOperationDelegate
- (void) searchDataReady:(NSArray*) searchResult;
@end
@interface ISSearchOperation : NSOperation {
id <ISSearchOperationDelegate> delegate;
NSString *searchTerm;
}
@property(nonatomic, retain) NSString *searchTerm;
@property(nonatomic, assign) id delegate;
- (id) initWithSearchTerm:(NSString*) searchString;
@end
Lorsqu'un objet extension NSOperation est ajouté à un NSOperationQueue, l'objet de file d'attente essaie d'appeler une méthode « principale » sur le NSOperation, vous devez par conséquent, enveloppez votre tâche dans cette méthode. (notez qu'après chaque sous-tâche terminée, je teste si elle s'est bien déroulée et "return" sinon.) La classe NSOperation a une propriété appelée isCancelled Cette propriété peut être définie par NSOperationQueue, donc vous devez également tester si qui a été défini lors de votre fin de principal pour résumer, vous testez de l'intérieur du principal si chaque étape est allé vous vouliez et vous tester si quelque chose à l'extérieur a annulé votre tâche):..
- (id) initWithSearchTerm:(NSString*) searchString {
if (self = [super init]) {
[self setSearchTerm:searchString];
}
return self;
}
- (void) main {
[self performSelector:@selector(timeOut) withObject:nil afterDelay:4.0];
if ([self isCancelled]) return;
NSData *resultData = [self searchWebServiceForString:self.searchTerm];
if (resultData == nil) return;
if ([self isCancelled]) return;
NSArray *result = [self parseJSONResult:resultData];
if ([self isCancelled]) return;
if (result == nil) return;
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[delegate performSelectorOnMainThread:@selector(searchDataReady:) withObject:result waitUntilDone:YES];
}
// Je n'ai pas copié l'implémentation de toutes les méthodes que j'appelle pendant main, mais j'espère que vous comprenez qu'il s'agit juste de "tâches" qui doivent être complétées avec succès avant que la prochaine sous-tâche puisse être calculée. Donc d'abord, j'ai mis un test de délai d'attente, puis je reçois mes données du service Web, puis je l'analyse.
Ok pour que tout cela se passe, vous avez besoin d'une file d'attente.
Ainsi, dans la classe que vous voulez être le délégué pour cette opération vous faites ceci:
quelque part mis en place une file d'attente:
NSOperationQueue *q = [[NSOperationQueue alloc] init];
[self setQueue:q];
[q release];
- (void) doSearch:(NSString*) searchString {
[queue cancelAllOperations];
ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
[searchOperation setDelegate:self];
[queue addOperation:searchOperation]; //this makes the NSOperationQueue call the main method in the NSOperation
[searchOperation release];
}
//the delegate method called from inside the NSOperation
- (void) searchDataReady:(NSArray*) results {
//Data is here!
}
Certains des avantages avec NSOperations est que du point de l'appelant de vue, nous faisons simplement un objet, définir un délégué, attendez la réponse. Mais dans les coulisses, une série de tâches threadées qui peuvent être annulées à tout moment est exécutée, et d'une manière qui peut gérer si les tâches enfilées échouent. Comme vous pouvez le voir dans la méthode doSearch, il commence par annuler toutes les opérations précédentes, je l'ai fait dans une application où je chercherais un service Web chaque fois qu'un utilisateur a tapé une lettre dans un mot. Cela signifie que si l'utilisateur recherchait "bonjour monde" - je ferais une recherche pour "h", puis "il", puis "hel", puis l'enfer ", puis" bonjour "etc Je voulais arrêter et nettoyer la tâche "h" dès que l'utilisateur a tapé le "e", car il était alors obsolète J'ai découvert que NSOperation était le seul moyen qui donnait la réactivité du threading et aucun des désordres qui accompagnent habituellement de nombreux threads les uns sur les autres
J'espère que vous pouvez l'utiliser pour commencer :)