NSOperationQueueのaddOperationWithBlockをキャンセルする方法。

こんにちは、JAGA(ja_gaimopotato)です。
NSOperationQueueaddOperationWithBlockをキャンセルする方法を考えました。

果たして、どれがベストなのか。## cancelAllOperationsを呼ぶと
色々と非同期なコードを書くときにお世話になっている、NSOperationQueueaddOperationWithBlockメソッド。

NSOperationQueueには、cancelAllOperationsというメソッドがあります。
その名前のごとくNSOperationを全てキャンセルするものだと思っていました。
ですが、これはNSOperationクラスのcancelメソッドを呼び出すだけのようですので、希望するキャンセル時の動作を実装したサブクラスが必要です。

キャンセルの手段を考える

特にaddOperationWithBlockNSBlockOperationではキャンセル時の動作が指定されていないようですので、どうするか考えました。

サブクラスを書かないで、キャンセルするとなるとループ内で判定するとか。

NSOperationQueue *queue = [NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{

        // しばらく終わらない処理
        while () {

            // メンバ変数でキャンセルかどうかを判断
            if (_cancelFlagOn == YES ) return;
        }

}]; 

__weakを利用した弱参照のweakBlockOperationをBlock内で評価するとか。

調べてみるとループ内ということなら他の方法もあるようでした。

NSBlockOperationを先に変数blockOperationとして捕捉しておいて、普通にaddOperationで加えるという方法をとって、__weakを利用した弱参照のweakBlockOperationをBlock内で評価しています。

ループ内で、weakBlockOperationがキャンセルされている場合は、そのBlockを終了するという処理をします。

NSBlockOperation *blockOperation = [[NSBlockOperation alloc] init];
 __weak NSBlockOperation *weakBlockOperation = blockOperation;

    [operation addExecutionBlock: ^ {

           // しばらく終わらない処理  
        while () {

         // ループ内でキャンセルを捕捉する。  
                if ([weakBlockOperation isCancelled]) return;
        }

 }];

 [_queue addOperation:blockOperation];

というようなコードになります。

cocoa – [NSOperation cancelAllOperations]; does not stop the operation – Stack Overflow

ループ以外に閃かなかった。

どちらにしろ、ループ内でしかキャンセルする方法がないので、他の方法がないか模索中です。
現在の結論としては、サブクラス書くしかないかな。
ということになりました。

これからも更新を続けていきますので、Feedlyへの登録をお願いします!

follow us in feedly

コメントを残す

メールアドレスが公開されることはありません。