LoginSignup
0
0

More than 5 years have passed since last update.

NSOperationを使って複数のNCMBリクエストを実行し、メインスレッドに戻す方法

Last updated at Posted at 2017-05-23

mBaaSで、複数オブジェクト操作APIの提供終了に伴い、for文等で複数オブジェクト操作を行った際に、処理が完了した後にメインスレッドに戻す必要性が出てきました。
http://info.biz.nifty.com/mb/2017/03/api-2.html

今回は、NSOperationを利用してその処理を行ってみようと思います。

NSOperationのサブクラスを作成する

RequestOperation.h
#import <Foundation/Foundation.h>
#import <NCMB/NCMB.h>

@interface RequestOperation : NSOperation

@property (nonatomic) NCMBObject *object;
@property (nonatomic) BOOL isExecuting, isFinished;

- (id)initWithObject:(NCMBObject *)object;

@end 
RequestOperation.m
#import "RequestOperation.h"

@implementation RequestOperation

- (id)initWithObject:(NCMBObject *)object {
    self = [super init];
    if (self) {
        _object = object;
    }
    _isExecuting = NO;
    _isFinished = NO;
    return self;
}

- (void) start {
    self.isExecuting = YES;
    // データストアへの登録を実施
    [self.object saveInBackgroundWithBlock:^(NSError *error) {
        if (error){
            // 保存に失敗した場合の処理
        } else {
            // 保存に成功した場合の処理
        }
        self.isExecuting = NO;
        self.isFinished = YES;
    }];
    // 並列実行モードで動かす
    do {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                 beforeDate:[NSDate distantFuture]];
    } while (self.isExecuting);
}

@end

処理を実行するクラスでの処理

プロパティ
@property (nonatomic) void (^finishedBlock) ();

処理を実行するメソッド内での処理
    NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
    // NSOperationQueueのカウント数の監視を登録
    [operationQueue addObserver:self
                          forKeyPath:@"operationCount"
                             options:NSKeyValueObservingOptionNew
                             context:nil];

    for (int i = 0; i < 5; i++) {
        // testクラスのNCMBObjectを作成
        NCMBObject *object = [NCMBObject objectWithClassName:@"test"];
        // オブジェクトに値を設定
        [object setObject:@"value" forKey:@"key"];
        // リクエストの作成
        RequestOperation *operation = [[RequestOperation alloc] initWithObject:object];
        // 処理の開始
        [operationQueue addOperation:operation];

    }

    // 処理が完了した時のblock
    self.finishedBlock = ^(){
        // メインスレッドに戻ってきた時に行う処理
    };

// NSOperationQueueのカウント数に変化があると呼ばれる
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {

    // operationCountが0になり処理が完了した時にメインスレッドでblockを実行する
    if ([keyPath isEqualToString:@"operationCount"]) {
        if ([[change objectForKey:@"new"] intValue] == 0) {
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.finishedBlock();
            }];
        }
    }
}

waitUntilAllOperationsAreFinishedメソッドについて

waitUntilAllOperationsAreFinishedメソッドを利用して、キューに入っているオペレーションが完了するのを待つ方法があります。
しかし、NCMBのsaveInBackgroundWithBlockはNSURLConnectionに[NSOperationQueue mainQueue]を設定しているため、waitUntilAllOperationsAreFinishedを利用して完了するのを待っても処理が実行されません。
そのため、今回はKVOを利用する方法になっています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0