我在Swift中继承NSOperation
并需要覆盖isExecuting
和isFinished
属性,因为我正在覆盖start
方法。
我遇到的问题是如何保留键值观察(KVO),同时还能覆盖这些属性。
通常在Obj-C中,在类扩展readwrite
定义中将属性重新声明为JSONOperation ()
非常容易。但是,我在Swift中看不到同样的功能。
示例:
class JSONOperation : NSOperation, NSURLConnectionDelegate
{
var executing : Bool
{
get { return super.executing }
set { super.executing } // ERROR: readonly in the superclass
}
// Starts the asynchronous NSURLConnection on the main thread
override func start()
{
self.willChangeValueForKey("isExecuting")
self.executing = true
self.didChangeValueForKey("isExecuting")
NSOperationQueue.mainQueue().addOperationWithBlock(
{
self.connection = NSURLConnection(request: self.request, delegate: self, startImmediately: true)
})
}
}
所以这是我提出的解决方案,但它感觉非常丑陋和hacky:
var state = Operation()
struct Operation
{
var executing = false
var finished = false
}
override var executing : Bool
{
get { return state.executing }
set { state.executing = newValue }
}
override var finished : Bool
{
get { return state.finished }
set { state.finished = newValue }
}
请告诉我有更好的方法。我知道我可以创建一个var isExecuting
而不是整个struct
,但后来我有两个类似命名的属性,这些属性引入歧义并使其公开可写(我不想要)。
哦,我会为一些访问修饰符关键字做些什么...
答案 0 :(得分:29)
正如David所说,你可以在子类属性覆盖中实现getter和setter。
但是,在定义asynchronous
/ concurrent
操作(即那些将异步完成的操作)时,为{{1}调用will
/ didChangeValueForKey
至关重要}和isFinished
。如果你不这样做,操作就不会被释放,依赖关系不会被尊重,你会遇到问题isExecuting
等等。)
所以我建议:
maxConcurrentOperationCount
顺便说一下,检查private var _executing: Bool = false
override var executing: Bool {
get {
return _executing
}
set {
if _executing != newValue {
willChangeValueForKey("isExecuting")
_executing = newValue
didChangeValueForKey("isExecuting")
}
}
}
private var _finished: Bool = false;
override var finished: Bool {
get {
return _finished
}
set {
if _finished != newValue {
willChangeValueForKey("isFinished")
_finished = newValue
didChangeValueForKey("isFinished")
}
}
}
和_executing
是否已更改并不重要,但在编写自定义_finished
方法等时,它有时会很有用。
<强>更新强>
人们不止一次指出cancel
中新的finished
/ executing
个属性,并得出结论,相应的KVO密钥为NSOperation.h
/ {{1} }。通常,在编写符合KVO标准的属性时,这是正确的。
但finished
未遵守executing
/ NSOperationQueue
键。它会观察finished
/ executing
个键。如果您没有对isFinished
/ isExecuting
密钥执行KVO调用,则可能会出现问题(特别是异步操作之间的依赖关系将失败)。它很烦人,但这是如何运作的。 并发编程指南的Operation Queues章节中的配置并发执行操作部分非常清楚需要执行isFinished
的主题/ isExecuting
KVO致电。
虽然并发编程指南已过时,但它对isFinished
/ isExecuting
KVO非常明确。并且可以轻松地凭经验验证指南仍然反映实际的isFinished
实施。通过演示,在isExecuting
中使用异步/并发NSOperation
子类时,请参阅this Github demonstration of the appropriate KVO中的单元测试。
答案 1 :(得分:23)
从快速书中:
通过在子类属性覆盖中提供getter和setter,可以将继承的只读属性作为读写属性。
我想你会发现这有效:
override var executing : Bool {
get { return _executing }
set {
willChangeValueForKey("isExecuting")
_executing = newValue
didChangeValueForKey("isExecuting")
}
}
private var _executing : Bool
答案 2 :(得分:10)
Swift 3.0回复更新:
private var _executing : Bool = false
override var isExecuting : Bool {
get { return _executing }
set {
guard _executing != newValue else { return }
willChangeValue(forKey: "isExecuting")
_executing = newValue
didChangeValue(forKey: "isExecuting")
}
}
private var _finished : Bool = false
override var isFinished : Bool {
get { return _finished }
set {
guard _finished != newValue else { return }
willChangeValue(forKey: "isFinished")
_finished = newValue
didChangeValue(forKey: "isFinished")
}
}