Last active
May 22, 2024 07:15
-
-
Save Sorix/57bc3295dc001434fe08acbb053ed2bc to your computer and use it in GitHub Desktop.
Subclass of NSOperation (Operation) to make it asynchronous in Swift 3, 4, 5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by Vasily Ulianov on 09.02.17, updated in 2019. | |
// License: MIT | |
import Foundation | |
/// Subclass of `Operation` that adds support of asynchronous operations. | |
/// 1. Call `super.main()` when override `main` method. | |
/// 2. When operation is finished or cancelled set `state = .finished` or `finish()` | |
open class AsynchronousOperation: Operation { | |
public override var isAsynchronous: Bool { | |
return true | |
} | |
public override var isExecuting: Bool { | |
return state == .executing | |
} | |
public override var isFinished: Bool { | |
return state == .finished | |
} | |
public override func start() { | |
if self.isCancelled { | |
state = .finished | |
} else { | |
state = .ready | |
main() | |
} | |
} | |
open override func main() { | |
if self.isCancelled { | |
state = .finished | |
} else { | |
state = .executing | |
} | |
} | |
public func finish() { | |
state = .finished | |
} | |
// MARK: - State management | |
public enum State: String { | |
case ready = "Ready" | |
case executing = "Executing" | |
case finished = "Finished" | |
fileprivate var keyPath: String { return "is" + self.rawValue } | |
} | |
/// Thread-safe computed state value | |
public var state: State { | |
get { | |
stateQueue.sync { | |
return stateStore | |
} | |
} | |
set { | |
let oldValue = state | |
willChangeValue(forKey: state.keyPath) | |
willChangeValue(forKey: newValue.keyPath) | |
stateQueue.sync(flags: .barrier) { | |
stateStore = newValue | |
} | |
didChangeValue(forKey: state.keyPath) | |
didChangeValue(forKey: oldValue.keyPath) | |
} | |
} | |
private let stateQueue = DispatchQueue(label: "AsynchronousOperation State Queue", attributes: .concurrent) | |
/// Non thread-safe state storage, use only with locks | |
private var stateStore: State = .ready | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Sorix I have a question related to this. I update dictionary as you did with array. How that can be solved? So basically result of every operation I need to keep somewhere in order to access it later. thx