Why do I get a crash clearing block-based KVO on self with NSManagedObject?

I am seeing a crash when trying to clear an NSKeyValueObservation on an NSOrderedSet on a NSManagedObject.


I am trying to set the observation to nil in willTurnToFault but I get an EXC_BAD_ACCESS doing so.


Trying to call invalidate() on the NSKeyValueObservation has no effect in willturnToFault(), and an error will follow: "...deallocated while key value observers were still registered with it."


I have created a simple project that replicates the issue when run in debug:

Github - /GilesHammond/KVO-Core-Data-Crash


The definition of the crashing NSManagedObject is below. Any insights greatly appreciated!

Thank you.


public class Matter: Point
        {
            override public func awakeFromFetch() {
                super.awakeFromFetch()
                print("\(hosts)") // Initialise lazy member and set observation
            }


            public override func willTurnIntoFault() {
                super.willTurnIntoFault()
                hostsObservation = nil // <-- EXC_BAD_ACCESS
            }


            @objc dynamic public internal(set) lazy var hosts: [Point] = {
                hostsObservation = observe(\.hostConnections_) { [unowned self] data, change in } // Empty observation closure
                return []
            }()


            private var hostsObservation: NSKeyValueObservation?
        }


// Matter+CoreDataProperties.swift - auto generated
    extension Matter {


        @nonobjc public class func fetchRequest() -> NSFetchRequest {
            return NSFetchRequest(entityName: "Matter")
        }


        @NSManaged public var hostConnections_: NSOrderedSet?


    }

Replies

This turned out to be a system bug when using NSKeyValueObservation on Core Data within a module. Logged with Feedback assistant.