我有一个具有复杂关系的Core Data模型,该模型已使用中间的“连接”对象(此问题的更多上下文:Maintaining Complex Unidirectional Relationships in Core Data)进行了建模。
我不希望使用该模型的代码了解中间连接对象,因此我向我的主要托管对象添加了一个数组属性,该属性公开了所连接的对象(我也希望可以观察到)。
@objc dynamic public internal(set) lazy var hosts: [Point] = {
let initialHosts = hostConnections.map { $0.superpoint }
hostsobservation = track(\Matter.hostConnections_!,on: self,mapping: \HostConnection.superpoint,to: #keyPath(hosts))
return initialHosts
}()
上面的代码在初始化nsorderedset
数组时(使用可以在我所有连接类型上创建此模式的通用函数)对hosts
连接的建立观察。观测结果如期发生。
我使willTurnIntoFault()
中的观察结果无效:
override public func willTurnIntoFault() {
hostsobservation?.invalidate()
print("hostsobservation \(hostsobservation) invalidated")
super.willTurnIntoFault()
}
但是,当在NSKVODeallocate
中释放该对象时,我崩溃了。
hostsobservation Optional(<_NSKeyValueObservation: 0x600000ccd920>) invalidated
2019-11-04 12:02:06.467620+0000 Frame[27900:5614740] [General] An instance 0x60000300bc30 of class FrameGraph.Subject_Subject_ was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x6000002d6ae0> (
<NSKeyValueObservance 0x600000ccd950: Observer: 0x600000ccd920,Key path: hostConnections_,Options: <New: NO,Old: NO,Prior: NO> Context: 0x0,Property: 0x600000c78b10>
...
0 CoreFoundation 0x00007fff3f590e45 __exceptionPreprocess + 256
1 libobjc.A.dylib 0x00007fff6a1e63c6 objc_exception_throw + 48
2 CoreFoundation 0x00007fff3f590c77 +[NSException raise:format:] + 193
3 Foundation 0x00007fff4180f349 NSKVODeallocate + 442
4 CoreData 0x00007fff3f060772 -[_PfmanagedObjectReferenceQueue _processReferenceQueue:] + 1154
正如您从日志中看到的那样,在崩溃声称是问题之前,我正在使观察无效。如果我尝试将观察值设置为nil
在willTurnToFault()
中,我的应用此时崩溃了。
我是Core Data的新手,有人可以帮助我解决我在这里缺少的内容吗?为什么观察到自己属性的对象会以这种方式崩溃?
编辑1:
我的跟踪功能如下:
internal func track<P: Point,C: Connection>(_ trackedPath: KeyPath<P,nsorderedset>,on point: P,mapping connectionPath: KeyPath<C,Point>,to mappedPoints: String)
-> NSKeyValueObservation
{
return point.observe(trackedPath) { [unowned point] data,change in
// ...
}
}
编辑2:
我已经将崩溃代码剥离为此:
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<Matter> {
return NSFetchRequest<Matter>(entityName: "Matter")
}
@NSManaged public var hostConnections_: nsorderedset?
}
我不知道在hostsobservation
崩溃时将nil
设置为willTurnToFault()
会发生什么。
我正在Xcode 11.1中使用Swift 5构建OSX 10.12。
编辑3:
转载于一个新的简单项目:https://github.com/GilesHammond/KVO-Core-Data-Crash