Details
-
Type:
Bug
-
Status: Open
-
Priority:
Medium
-
Resolution: Unresolved
-
Component/s: Foundation
-
Labels:None
-
Environment:
Version 9.0 beta 6 (9M214v)
Description
MyHostObject owns MyObject and observes changes of it's value:
import Foundation class MyObject: NSObject { @objc dynamic var value: Int = 0 } class MyHostObject: NSObject { @objc dynamic let myObject = MyObject() var _observation: NSKeyValueObservation? override init() { super.init() _observation = observe(\.myObject.value, options: [.new]) { (myObject, change) in print("value changed to \(change.newValue!)") } } deinit { // `myObject` is in Limbo right now, but I can still call it's methods and, hopefully, remove observation _observation?.invalidate() _observation = nil } } var myHostObject: MyHostObject? = MyHostObject() myHostObject = nil // crashing here with: // *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x101c10290 of class issue_NSKeyValueObservation.MyHostObject was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x101c14ed0> ( <NSKeyValueObservance 0x101c14c20: Observer: 0x101c115f0, Key path: myObject.value, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x101c129b0> )'
With Objective-C equivalent, MyHostObject would still be able to remove observation from myObject.
This is happening because NSKeyValueObservation holds a weak reference to an object. That weak reference turns to nil too soon. My suggestion is to use unowned or Unmanaged<MyObject> reference.