2013-10-15 8 views
6

私はたくさんのデータをソートするNSOperation(サブクラス)をたくさん作成しています。それらが完了したら、私はそれらのデータを "返す"ようにして、変更可能な配列などに入れてください。順序は関係ありません。NSOperationからデータを返しますか?

これは可能ですか?

答えて

4

NSOperationサブクラスでデリゲートを宣言します。次いで、操作の終了UI

-(void)YourOperationDidFinish:(YourOperation *)downloader { 
    if(downloader.downloadItem) { 
     // processing with your object  
    } 
} 
+1

+1明らかに、 '@ selector'とデリゲートのメソッドで同じメソッド名を参照する必要があります。たとえば、デリゲートのメソッドが 'yourOperationDidFinish:'である場合、 '@selector(yourOperationDidFinish:)'を参照します。より良い、あなたはおそらく[プロトコル](https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Protocol.html#//apple_ref/doc/uid/TP40008195-CH45 -SW1)を使用して、ここであいまいさを解消します。また、この答えに暗黙のうちに、 'delegate'プロパティ' weak'を宣言することは賢明でしょう。 – Rob

14

if([self.delegate respondsToSelector:@selector(YourDelegate:)]) { 
    [(NSObject *)self.delegate performSelectorOnMainThread:@selector(YourDelegate:) withObject:self waitUntilDone:NO]; 
} 

後プロトコルデリゲートパターンの代わりに、完了ブロックです。例えば、いくつかのランダムなNSURLConnection基づく動作中、Iは、成功した場合NSDataを返し終了ブロックtypedef(ちょうど後ブロックの構文を簡略化するために)、またはNSErrorを定義しない場合:

typedef void(^CustomOperationCompletionBlock)(NSData *data, NSError *error); 

Iは、次に定義することができ私のNSOperationサブクラス、例えばブロックプロパティ:

@property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock; 

は、私はよく、私はanythinに加えて、(initプロセス中にその完了ブロックを設定できます私の運転の私init方法の表現を持っていますグラム他の私は、初期化したい):

- (instancetype)initWithURL:(NSURL *)url successFailureBlock:(CustomOperationCompletionBlock)successFailureBlock; 

私の操作中にエラーおよび/または成功を扱う私の様々な方法は、データのバックを渡すためにその完了ブロックを呼び出します。

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    if (self.successFailureBlock) { 
     // whether you call the completion block on the main queue, or use whatever queue the operation is using, is up to you. Here I'll call the completion block on the main queue: 

     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      self.successFailureBlock(nil, error); 
     }]; 
    } 

    [self completeOperation]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    if (self.successFailureBlock) { 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      self.successFailureBlock(self.data, nil); 
     }]; 
    } 

    [self completeOperation]; 
} 

そして、へカスタムの完了ブロックハンドラでこの操作を使用します。私が操作を開始するときに、カスタムの完了ブロックを渡すだけです。たとえば、これが成功した場合にデータを保存し、またはされていない場合、エラーを記録します:明らかに

CustomOperation *operation = [[CustomOperation alloc] initWithURL:url successFailureBlock:^(NSData *data, NSError *error) { 
    if (error) 
     NSLog(@"CustomOperation error: %@", error); 
    else   
     [data writeToFile:path atomically:YES]; 
}]; 

[queue addOperation:operation]; 

、あなたが戻ってあなたの操作のために意味をなすものは何でもオブジェクトを渡すためにブロックtypedefを変更します。しかしこれは、NSOperationサブクラスがデータを返すためのブロックベースのメカニズムの基本パターンを示しています。

+1

良い答えRob。 –

関連する問題