:
stateQueue? , get set state, , sync:flags:execute sync:execute, .
"" , . , , . Operation, :
Multicore Considerations
... NSOperation, , . , , , -. , , . . .
, "-". "-" , (, sync, ), (, async ). WWDC 2012 , GCD XPC. , , dispatch_sync dispatch_barrier_async, Swift 3 , sync async(flags: .barrier).
:
NSObject, ["state"]? - . NSObject class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>, , .
, , state KVN isReady, isExecuting isFinished. KVN . : .
keyPathsForValuesAffectingValue . , .
, AsynchronousOperation, :
super.start(). start ( ):
, . super .
@objc, Swift 4.
execute, main, Operation.
isReady final. isReady ( , , ).
#keyPath, /.
KVN dynamic. willChangeValue didChangeValue .
finish, .finished, .
:
public class AsynchronousOperation: Operation {
@objc private enum OperationState: Int {
case ready
case executing
case finished
}
private let stateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".rw.state", attributes: .concurrent)
private var _state: OperationState = .ready
@objc private dynamic var state: OperationState {
get { return stateQueue.sync { _state } }
set { stateQueue.async(flags: .barrier) { self._state = newValue } }
}
open override var isReady: Bool { return state == .ready && super.isReady }
public final override var isExecuting: Bool { return state == .executing }
public final override var isFinished: Bool { return state == .finished }
public final override var isAsynchronous: Bool { return true }
open override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
if ["isReady", "isFinished", "isExecuting"].contains(key) {
return [#keyPath(state)]
}
return super.keyPathsForValuesAffectingValue(forKey: key)
}
public final override func start() {
if isCancelled {
state = .finished
return
}
state = .executing
main()
}
open override func main() {
fatalError("Subclasses must implement 'main'.")
}
public final func finish() {
if !isFinished { state = .finished }
}
}