NSOperationは非常に便利です。これを使用するには、NSOperationを拡張し、「main」メソッドをオーバーライドします。メインの方法では、計算やWebリクエストなどを行います。したがって、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の「main」メソッドを呼び出そうとするため、タスクをこのメソッドでラップする必要があります。(サブタスクが完了するたびに、うまくいったかどうかをテストし、うまくいかなかった場合は「戻る」ことに注意してください。NSOperationクラスにはisCancelledというプロパティがあります。このプロパティはNSOperationQueueによって設定できるため、メインの完了。要約すると、各ステップが希望どおりに進んだかどうかをメインの内側からテストし、外側の何かがタスクをキャンセルしたかどうかをテストします。):
- (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中に呼び出すすべてのメソッドの実装をコピーしていませんが、これらは単なる「タスク」であり、次のサブタスクを計算する前にそれぞれを正常に完了する必要があることを理解してください。そこで、最初にタイムアウトテストを実行し、次にWebサービスからデータを取得して、それを解析します。
これをすべて実行するには、キューが必要です。
したがって、この操作のデリゲートになりたいクラスでは、次のようにします。
どこかにキューを設定します:
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メソッドでわかるように、以前の操作をキャンセルすることから始まります。これは、ユーザーが単語に文字を入力するたびにWebサービスを検索するアプリで行いました。つまり、ユーザーが「hello world」を検索した場合、「h」、「he」、「hel」、「hell」、「hello」などを検索します。停止してクリーンアップしたかったのです。ユーザーが「e」を入力するとすぐに「h」タスクが廃止されたため、NSOperationがスレッドの応答性を提供する唯一の方法であり、通常は多くのスレッドを上に生成することに伴う混乱はないことがわかりました。お互いの。
あなたが始めるためにそれを使うことができることを願っています:)