【发布时间】:2017-09-19 13:06:10
【问题描述】:
我正在尝试在一个辅助项目中开始使用Operations,而不是在我的网络代码中散布基于闭包的回调来帮助消除嵌套调用。所以我在阅读这个主题时,遇到了this 实现:
open class AsynchronousOperation: Operation {
// MARK: - Properties
private let stateQueue = DispatchQueue(label: "asynchronous.operation.state", attributes: .concurrent)
private var rawState = OperationState.ready
private dynamic var state: OperationState {
get {
return stateQueue.sync(execute: {
rawState
})
}
set {
willChangeValue(forKey: "state")
stateQueue.sync(flags: .barrier, execute: {
rawState = newValue
})
didChangeValue(forKey: "state")
}
}
public final 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
}
// MARK: - NSObject
private dynamic class func keyPathsForValuesAffectingIsReady() -> Set<String> {
return ["state"]
}
private dynamic class func keyPathsForValuesAffectingIsExecuting() -> Set<String> {
return ["state"]
}
private dynamic class func keyPathsForValuesAffectingIsFinished() -> Set<String> {
return ["state"]
}
// MARK: - Foundation.Operation
public final override func start() {
super.start()
if isCancelled {
finish()
return
}
state = .executing
execute()
}
// MARK: - Public
/// Subclasses must implement this to perform their work and they must not call `super`. The default implementation of this function throws an exception.
open func execute() {
fatalError("Subclasses must implement `execute`.")
}
/// Call this function after any work is done or after a call to `cancel()` to move the operation into a completed state.
public final func finish() {
state = .finished
}
}
@objc private enum OperationState: Int {
case ready
case executing
case finished
}
这个Operation 子类有一些实现细节,我希望在理解方面有所帮助。
-
李>stateQueue属性的用途是什么?我看到它被state计算属性的get和set使用,但我找不到任何解释他们使用的sync:flags:execute和sync:execute方法的文档。 NSObject部分中返回["state"]的三个类方法的用途是什么?我没有看到它们在任何地方使用。我在NSObject、class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>中找到了,但这似乎并不能帮助我理解为什么要声明这些方法。
【问题讨论】:
-
仅供参考,这是一个相当严重的错误。
startdocumentation 说(添加了重点):“如果您正在实现并发操作,则必须重写此方法并使用它来启动您的操作。您的自定义实现不得在任何时候调用super。” -
@Rob 引用段落中的关键字是“并发”。这仅与不在操作队列中运行的操作相关。请参阅 _isAsynchronous 属性和本段:developer.apple.com/documentation/foundation/operation#1661231
-
@Rob 没有拍摄,但我邀请你仔细看看。我多年来一直在使用操作。甚至 Apple 在著名的 Advanced Operations WWDC2015 谈话中的示例代码也会在 start() 中覆盖并调用 super。我并不是说示例代码是完美的,但是。我的印象是说你不应该叫 super 的段落很容易被误解。
-
此外,Apple 称之为异步的操作是从 start() 生成一个新线程的操作。这与在后台队列中运行操作不同。
-
大声笑。我知道“异步操作”是什么意思。最重要的是,关于
start实现的文档再清楚不过了,他们多次重复警告:“在您的start()方法中,您永远不应该调用super”和“您的自定义实现[@987654342 @] 任何时候都不能打电话给super。”而且我不会将“高级 NSOperations”作为示例,因为正如您所暗示的那样,它的问题是臭名昭著和多方面的。但是,嘿,如果你想打电话给super,把自己打晕。但是应该预先警告未来的读者,因为如果您不小心,可能会导致问题。
标签: swift nsoperation