4
3

More than 3 years have passed since last update.

Operation (NSOperation) 実装方法

Last updated at Posted at 2019-10-25

Operationの実装方法には2種類あり、どちらのタイプも並列で処理されます。

タイプ 概要
non-concurrent タイプ 同期的なタスクをOperation化する
concurrent タイプ 非同期的なタスクをOperation化する

non-concurrentタイプ

画像の合成など同期的な処理をOperation化したい場合は、non-concurrent タイプを実装します。

以下のメソッドをオーバーライドします。

  • main()

実装例

class RequestOperation: Operation {
    func main() {
        //同期的なタスクを実装すること
        self.createImage()
        //main関数終了後自動的にqueueから削除される
    }
}

mainメソッド終了後、OperationQueueから削除される
したがって非同期的な処理が実装できないため、非同期的なタスクは concurrentタイプを実装します。

concurrentタイプ

ネットワークからのデータの取得やストレージへの保存など非同期的な処理をOperation化したい場合は、concurrentタイプを実装します。

以下のメソッドをオーバーライドします。

  • start() このメソッドから処理が抜けてもQueueから削除されません。
  • isFinished { get }
  • isExecuting { get }
  • isAsynchronous { get } ※もはや無視されている

以下の状態変更はKVOで通知します。

  • isFinished { set } この値がtrueになった時にOperationQueueから削除される
  • isExecuting { set }
  • isAsynchronous { set } ※もはや無視されている

処理がstartメソッドを抜けてもOperationQueueから削除されません。
OperationQueueからの削除はisFinishedプロパティがtrueになったときです。
(KVOで通知する必要があります。)

class RequestOperation: Operation {

    var object: Object? = nil

    enum State {
        case ready
        case executing
        case finished
    }

    private var state = State.ready {
        didSet {
            switch self.state {
            case .ready: break
            case .executing:
                self.isExecuting = true
            case .finished:
                self.isExecuting = false
                self.isFinished = true
            }
        }
    }

    private var _executing: Bool = false
    override var isExecuting: Bool {
        get {
            return _executing
        }
        set {
            if _executing != newValue {
                self.willChangeValue(for: \RequestOperation.isExecuting)
                _executing = newValue
                self.didChangeValue(for: \RequestOperation.isExecuting)
            }
        }
    }

    private var _finished: Bool = false;
    override var isFinished: Bool {
        get {
            return _finished
        }
        set {
            if _finished != newValue {
                self.willChangeValue(for: \RequestOperation.isFinished)
                _finished = newValue
                self.didChangeValue(for: \RequestOperation.isFinished)
            }
        }
    }

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

    override func start() {
        guard self.isCancelled == false else {
            // Queueから削除される
            self.state = .finshed
            return
        }

        self.state = .executing

        // データストアへの登録を実施
        object?.saveInBackground({ (error) in
            if error != nil {
                // 保存に失敗した場合の処理
            } else {
                // 保存に成功した場合の処理
            }
            // Queueから削除される
            self.state = .finished
        })

        // startメソッドが終了してもQueueから削除されない
    }
}

 参照

[Qiita] Operation(NSOperation)について
今読むと分かりにくかったのでまとめ直しました。

4
3
1

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
4
3