【Objective-C】NSOperationQueueを活用して、並列処理を行いながら、特定の処理を完了してから特定処理を行う方法について【Xcode11/iOS13対応】

こういう人に向けて発信しています。
・非同期的に同期的に処理される処理を待って特定処理をしたい人
・オペレーションの依存関係を調べている人
・Objective-C中級者

まずは失敗例です。

本来であれば並列処理されている「opA」の完了を待って、
「opB」を処理したいと考えております。

//NSOperationQueueを初期化する。
   NSOperationQueue *queue = [[NSOperationQueue alloc]init];
   
   //同時に並列処理するオペレーションタスクの上限数を設定する。
   queue.maxConcurrentOperationCount = 2;   //特に設定しなければシステム側が判定して並列処理数を確定させる。
   
   //オペレーションA初期化:5回ログを吐き出す処理を呼び出す
   NSOperation *opA = [NSBlockOperation blockOperationWithBlock:^{
       //5回 logを吐き出す処理
       for(int i=0; i<5; i++){
           NSLog(@"A roop");
           [NSThread sleepForTimeInterval:0.2];  //0.2秒停止する
       }
   }];
   
   //オペレーションA初期化:5回ログを吐き出す処理を呼び出す
   NSOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
       //5回 logを吐き出す処理
       for(int i=0; i<15; i++){
           NSLog(@"B roop");
           
       }
   }];
   
   //オペレーションキューにオペレーションAを追加する。
   [queue addOperation:opA];
   
   //オペレーションキューにオペレーションBを追加する。
   [queue addOperation:opB];

ログでは下記のようになります。
A処理とB処理が非同期的に実行されていますね。

2019-11-27 21:39:48.830980+0900 root_projectFile[15958:466662] A roop
2019-11-27 21:39:48.831049+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.831379+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.831528+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.831799+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.832195+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.832317+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.832470+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.833056+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.833587+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.833967+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.834464+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.835108+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.835683+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.836230+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:48.836854+0900 root_projectFile[15958:466661] B roop
2019-11-27 21:39:49.035032+0900 root_projectFile[15958:466662] A roop
2019-11-27 21:39:49.236345+0900 root_projectFile[15958:466662] A roop
2019-11-27 21:39:49.436917+0900 root_projectFile[15958:466662] A roop
2019-11-27 21:39:49.638005+0900 root_projectFile[15958:466662] A roop

解決:オペレーションの依存関係を追加する

    
- (void)demoMethod{
   
   //NSOperationQueueを初期化する。
   NSOperationQueue *queue = [[NSOperationQueue alloc]init];
   
   //同時に並列処理するオペレーションタスクの上限数を設定する。
   queue.maxConcurrentOperationCount = 2;   //特に設定しなければシステム側が判定して並列処理数を確定させる。
   
   //オペレーションA初期化:5回ログを吐き出す処理を呼び出す
   NSOperation *opA = [NSBlockOperation blockOperationWithBlock:^{
       //5回 logを吐き出す処理
       for(int i=0; i<5; i++){
           NSLog(@"A roop");
           [NSThread sleepForTimeInterval:0.2];  //0.2秒停止する
       }
   }];
   
   //オペレーションA初期化:5回ログを吐き出す処理を呼び出す
   NSOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
       //5回 logを吐き出す処理
       for(int i=0; i<15; i++){
           NSLog(@"B roop");
           
       }
   }];

   //オペレーションBが完了してからオペレーションAを実行する
   //注意:該当オペレーション2件がaddOperationされる前に依存関係を紐づける
   [opB addDependency:opA];
   
   //オペレーションキューにオペレーションAを追加する。
   [queue addOperation:opA];
   
   //オペレーションキューにオペレーションBを追加する。
   [queue addOperation:opB];

結局 依存関係を示すコードを1行追加してあげるだけで処理が可能です。

   [opB addDependency:opA];

ログは以下のようになります。
綺麗にA処理が終わってからB処理が行われていますね。

2019-11-27 21:42:23.597738+0900 root_projectFile[16038:469246] A roop
2019-11-27 21:42:23.798070+0900 root_projectFile[16038:469246] A roop
2019-11-27 21:42:24.000575+0900 root_projectFile[16038:469246] A roop
2019-11-27 21:42:24.201996+0900 root_projectFile[16038:469246] A roop
2019-11-27 21:42:24.407492+0900 root_projectFile[16038:469246] A roop
2019-11-27 21:42:24.609168+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.609537+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.609931+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.610200+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.610433+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.610647+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.610857+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.611078+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.611310+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.611952+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.612578+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.613263+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.614094+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.614936+0900 root_projectFile[16038:469249] B roop
2019-11-27 21:42:24.615754+0900 root_projectFile[16038:469249] B roop

この記事が気に入ったらサポートをしてみませんか?