在这个简单的代码(的Xcode 8.3),创建一个操作子类的实例,注册其isFinished
财产的志愿观测,并通过将其添加到我的队列启动操作:当注销操作的志愿观测isFinished
class MyOperation : Operation {
override func main() {
print("starting")
print("finishing")
}
}
class ViewController: UIViewController {
let q = OperationQueue()
override func viewDidLoad() {
super.viewDidLoad()
let op = MyOperation()
op.addObserver(self, forKeyPath: #keyPath(MyOperation.isFinished), options: [], context: nil)
self.q.addOperation(op)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("Observed \(keyPath)")
if let op = object as? Operation {
op.removeObserver(self, forKeyPath: #keyPath(MyOperation.isFinished))
}
}
}
正如你所看到的,我当然有一个observeValue(forKeyPath...
的实现,我的计划是在那里调用removeObserver(forKeyPath...
。
问题是我的应用程序崩溃,“MyOperation被释放,而关键值观察员仍然注册它”。我们打印“开始”和“结束”,但我们从不打印“观察”;该操作在之前不存在我收到了我的KVO通知。
这看起来像一个catch-22。如果我不能通过观察isFinished
删除观察者,那么我应该怎么做? [我可以通过向MyOperation添加我自己的KVO可观察属性来解决此问题,该属性在main
末尾处设置。但我应该这样做的想法很奇怪,是不是这正是为什么isFinished
是可观的,所以我可以做什么,我想在这里?]
难道这是https://developer.apple.com/library/content/technotes/tn2109/_index.html中提到的问题吗? - “使用键值观察(KVO)观察NSOperation的isFinished属性时可能会出现类似的问题,虽然KVO不保留观察者或观察者,但即使您删除了观察者-viewWillDisappear:方法,KVO通知可能已经在您的对象的运行中,如果发生这种情况,运行通知的线程最终可能会调用一个释放对象! –
@MartinR本节注释的是“自我”(观察者)可能不存在的危险,因此KVO通知可能会发送给不存在的对象。这是我的问题的反映;我的问题是,操作(观察者)将不存在而不向我发送我的KVO通知。 'self'是根视图控制器,并且无处可去。 – matt
是否有任何用处提及我尝试过,我可以看到:'开始完成Observed Optional(“isFinished”)'?我的应用程序不会*崩溃。我正在使用xcode 8.2,我希望我明白情况如何...... –