NSOperation очень полезен.Чтобы использовать его, вы расширяете NSOperation и переопределяете метод "main".В основном методе вы выполняете свои вычисления / веб-запрос и т. Д. Таким образом, NSOperation лучше всего подходит для задач, которые вы можете заключить в несколько простых шагов, после каждого шага вы проверяете, все ли в порядке, и либо переходите к следующему шагу, либо отменяете операцию.Как только это будет сделано, вы можете просто создать свою собственную пользовательскую NSOperation и передать ее объекту NSOperationQueue, и он позаботится о потоке, запуске, остановке очистки и т. Д.
В приведенном ниже примере я написал протоколчтобы справиться с завершением задачи, я бы посоветовал вам использовать этот подход вместо использования уведомлений - если только у вас нет нескольких объектов, о которых нужно немедленно уведомлять.
Создайте новый класс, который расширяет класс 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
Когда объект, расширяющий NSOperation, добавляется в NSOperationQueue, объект очереди пытается вызвать «основной» метод в NSOperation, поэтому вы должны обернуть свою задачу в этом методе.(обратите внимание, что после каждой выполненной подзадачи я проверяю, хорошо ли она прошла, и «возвращаюсь», если нет. Класс NSOperation имеет свойство под названием isCancelled Это свойство может быть установлено с помощью NSOperationQueue, поэтому вы также должны проверитьесли это было установлено во время вашего завершения main. Итак, резюмируем, вы проверяете изнутри main, прошел ли каждый шаг, как вы хотели, и вы проверяете, отменял ли что-то извне вашу задачу.):
- (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];
}
// Я не скопировал реализацию всех методов, которые я вызываю во время main, но я надеюсь, вы понимаете, что это просто «задачи», каждая из которых должна быть успешно выполнена, прежде чем следующая подзадача может быть вычислена.Итак, сначала я поставил там тест тайм-аута, затем я получаю свои данные из веб-службы и затем анализирую их.
Хорошо, чтобы все это заработало, вам нужна очередь.
Итакв классе, которым вы хотите быть делегатом для этой операции, вы делаете это:
где-то настраиваете очередь:
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!
}
Некоторым преимуществом с NSOperations является то, что с точки вызывающей сторонывид, мы просто создаем объект, устанавливаем делегата, ждем ответа.Но за кулисами запускается ряд многопоточных задач, которые можно отменить в любое время, и таким образом, чтобы они могли справиться, если многопоточные компоненты не работают.
Как видно из метода doSearch, он начинается с отменывсе предыдущие операции я выполнял в приложении, где каждый раз, когда пользователь вводил букву в слове, я искал веб-сервис.Это означает, что если бы пользователь искал «hello world» - я бы выполнил поиск «h», затем «he», затем «hel», затем «hell», затем «hello» и т. Д. Я хотел остановиться и убратьзадача "h", как только пользователь набрал "e", потому что она тогда устарела. Я обнаружил, что NSOperation был единственным способом, который давал отзывчивость многопоточности, и ни один из беспорядка, который обычно сопровождается порождением множества потоков сверхудруг друга.
Надеюсь, вы можете использовать его, чтобы начать:)