【Objective-C】NSOperationQueueを活用した逐次処理の方法について【Xcode11/iOS13対応】

こういう人に向けて発信しています。
・逐次処理を行いたい人
・メインスレッドではなくマルチスレッドにて処理を行いたい人
・Objective-C中級者以上

そもそも逐次処理とは?

順次処理、シリアル処理とも呼ぶ。データが保存された順番で処理を実行すること。

以上のように

NSOperationQueueを活用する。

NSOperationQueueにオペレーションタスクを追加して、
並列処理数を上限1と指定します。

#import "ViewController.h"
#import "DataManager.h"
#import "DemoViewController.h"


@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   
   //NSOperationQueueを初期化する。
   NSOperationQueue *queue = [[NSOperationQueue alloc]init];
   
   //同時に並列処理するオペレーションタスクの上限数を設定する。
   queue.maxConcurrentOperationCount = 1;
   
   //オペレーションA初期化:5回ログを吐き出す処理を呼び出す
   NSOperation *opA = [NSBlockOperation blockOperationWithBlock:^{
       [self roopA];
   }];
   
   //オペレーションB初期化:xibの背景色を黄色にだけ変更したかUIViewControllerをモーダル表示し、表示完了した直後に画面を下げる処理
   NSOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
       dispatch_async(dispatch_get_main_queue(), ^{
           //デモVCを上げて、上げ終わった後下げる処理
           DemoViewController *demoVC = [[DemoViewController alloc]init];
           [self presentViewController:demoVC animated:YES completion:^{
               [self dismissViewControllerAnimated:YES completion:nil];
               NSLog(@"B処理完了");
           }];
           
       });
   }];
   
   //オペレーションC初期化:ネットワーク通信シングルトンを参照し、URLSessionを用いて同期的に通信結果を取得する処理
   NSOperation *opC = [NSBlockOperation blockOperationWithBlock:^{
       DataManager *dataManager = [DataManager sharedManager];
       NSDictionary *dic = [dataManager sessionSyncRequest:@"https://www.json-generator.com/api/json/get/cezpmhLKZK?indent=2"];
       NSLog(@"C処理完了");
       
   }];

   //オペレーションタスクAをオペレーションキューに追加する。
   [queue addOperation:opA];
   
   //オペレーションタスクBをオペレーションキューに追加する。
   [queue addOperation:opB];
   
   //オペレーションタスクCをオペレーションキューに追加する。
   [queue addOperation:opC];
   
   /*
    オペレーションキューはオペレーションタスクが追加されたら処理される。
    上記オペレーションキューの上限並列処理数を1としている。
    オペレーションキューに追加した順に逐次処理(終わり次第処理される)が行われる。
    */
   
}

- (void)roopA{
   //5回 logを吐き出す処理
   for(int i=0; i<5; i++){
       NSLog(@"A roop");
   }
}

@end

上記コード内では以下のような処理を行なっております。
(1)A処理:同期的なfor文でログを出力する
(2)B処理:xibの背景色を黄色にだけ変更したかUIViewControllerをモーダル表示し、表示完了した直後に画面を下げる処理
  ※画面描画はメインスレッドで行う必要であるが同期的な処理内容ではない。
(3)C処理:同期的な通信を行う処理

上記コードのログがこちらです。

2019-11-27 20:49:00.805474+0900 root_projectFile[14609:439013] A roop
2019-11-27 20:49:00.806449+0900 root_projectFile[14609:439013] A roop
2019-11-27 20:49:00.807196+0900 root_projectFile[14609:439013] A roop
2019-11-27 20:49:00.807349+0900 root_projectFile[14609:439013] A roop
2019-11-27 20:49:00.807632+0900 root_projectFile[14609:439013] A roop
2019-11-27 20:49:01.523578+0900 root_projectFile[14609:439020] B処理完了
2019-11-27 20:49:02.060974+0900 root_projectFile[14609:438934] C処理完了

同期的な処理を待ってくれるのは分かるんですが、(何もしなくても同期的な処理を行うと処理が止まるため)
B処理のような同期的ではない処理につきましても、処理が行われるまで待機し、また完了ブロック(completion)まで待ってくれています。





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