NSOperation属性重写(isExecuting / isFinished)

我在Swift中NSOperation ,并且需要重写isExecutingisFinished属性,因为我重写了start方法。

我遇到的问题是如何保留键值观察(KVO),同时也能够覆盖这些属性。

通常在Obj-C中,这将是相当容易重新声明类扩展JSONOperation ()定义中的readwrite属性。 但是,我并没有在Swift中看到这个function。

例:

 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) }) } } 

所以这里是我提出的解决scheme,但它感觉非常丑陋和黑客:

 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 ,但是,我有两个相似的命名属性,它引入了歧义,也使它公开可写(我不想)。

哦,我会做一些访问修饰符关键字…

从迅捷书:

您可以通过在子类属性重写中提供getter和setter来呈现inheritance的只读属性作为读写属性。

我想你会发现这个工作:

 override var executing : Bool { get { return _executing } set { willChangeValueForKey("isExecuting") _executing = newValue didChangeValueForKey("isExecuting") } } private var _executing : Bool 

正如David所说,你可以在子类属性覆盖中实现一个getter和setter。

但是,当定义asynchronous / concurrent操作(即那些将asynchronous完成的操作)时,为isFinishedisExecuting调用will / didChangeValueForKey isExecuting 。 如果你不这样做,操作将不会被释放,依赖关系将不被遵守,你将有问题是maxConcurrentOperationCount等)。

所以我会build议:

 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") } } } 

顺便说一下,检查_finished_finished是否已经改变并不重要,但是在编写自定义的cancel方法等时有时会很有用。


更新:

人们不止一次地指出NSOperation.h的新的finished / executing属性,并得出结论:适当的KVO键将被finished / executing 。 一般来说,在编写符合KVO标准的属性时,这是正确的。

NSOperationQueue没有观察finished / executing键。 它观察isFinished / isExecuting键。 如果您不执行isFinished / isExecuting键的KVO调用,则可能会出现问题(特别是asynchronous操作之间的依赖关系将失败)。 这很烦人,但这就是它的工作原理。 “ 并发编程指南”的“ 操作队列”一章中的“为并发执行configuration操作”部分对于需要执行isFinished / isExecuting KVO调用的主题非常明确。

而“ 并发编程指南”的date是关于isFinished / isExecuting KVO的。 人们可以很容易地validation指南仍然反映了实际的NSOperation实施。 通过演示,在NSOperationQueue使用asynchronous/并发NSOperation子类时,请参阅此Github演示中适当KVO的unit testing。

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") } }