在這個簡單的代碼(的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,我希望我明白情況如何...... –