LoginSignup
2
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-05-23

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

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

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

RequestOperation.swift
class RequestOperation: Operation {

    var object:NCMBObject? = nil

    private var _executing: Bool = false
    override var isExecuting: Bool {
        get {
            return _executing
        }
        set {
            if _executing != newValue {
                willChangeValue(forKey: "isExecuting")
                _executing = newValue
                didChangeValue(forKey: "isExecuting")
            }
        }
    }

    private var _finished: Bool = false;
    override var isFinished: Bool {
        get {
            return _finished
        }
        set {
            if _finished != newValue {
                willChangeValue(forKey: "isFinished")
                _finished = newValue
                didChangeValue(forKey: "isFinished")
            }
        }
    }

    init(object:NCMBObject?) {
        super.init()
        self.object = object
    }

    override func start() {
        _executing = true
        // データストアへの登録を実施
        object?.saveInBackground({ (error) in
            if error != nil {
                // 保存に失敗した場合の処理
            } else {
                // 保存に成功した場合の処理
            }
            self._executing = false
            self._finished = true
        })
        // 並列実行モードで動かす
        repeat {
            RunLoop.current.run(mode: RunLoopMode.defaultRunLoopMode, before: NSDate.distantFuture)
        } while isExecuting
    }
}


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

プロパティ
var finishedBlock: (() -> Void)?

処理を実行するメソッド内での処理
let operationQueue = OperationQueue.init()
// OperationQueueのカウント数の監視を登録
operationQueue.addObserver(self, forKeyPath: "operationCount", options: .new, context: nil)

for _ in 1...5 {
    // testクラスのNCMBObjectを作成
    let object = NCMBObject.init(className: "test")
    // オブジェクトに値を設定
    object?.setObject("value", forKey: "key")
    // リクエストの作成
    let operasion = RequestOperation.init(object :object)
    // 処理の開始
    operationQueue.addOperation(operasion)
}

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

// NSOperationQueueのカウント数に変化があると呼ばれる
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    // operationCountが0になり処理が完了した時にメインスレッドでblockを実行する
    if keyPath == "operationCount" {
        if change?[NSKeyValueChangeKey.newKey] as! Int == 0 {
            OperationQueue.main.addOperation({ 
                self.finishedBlock!()
            })
        }
    }
}

waitUntilAllOperationsAreFinishedメソッドについて

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

2
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
2
0