我有一个基于NSDocument
的macOS应用程序,带有核心数据,从本质上讲,一次只能打开一个文档。因此,当打开新文档时,我会关闭当前打开的文档。所有与文档相关的UI都在一个单独的窗口控制器中,一切都很好。
但我也有一个菜单栏项目,它可以切换一个单独的窗口,显示有关文档的一些信息。UI是绑定到CCD_ 3的简单CCD_。数组控制器的managagedObjectContext
属性是在当前文档更改时设置的。这总是导致EXC_BAD_INSTRUCTION
崩溃。
为了缩小问题范围,我完全删除了数组控制器的所有绑定和任何其他操作。车祸已经过去了。我还在代码中创建了一个新的testArrayController
,看看那里发生了什么,确信我可以重现崩溃:
let testArrayController = NSArrayController()
var document: Document? {
didSet {
if document != nil {
testArrayController.managedObjectContext = document?.managedObjectContext
testArrayController.prepareContent() // <---- this causes the crash later on
} else {
testArrayController.managedObjectContext = nil
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
testArrayController.entityName = "MyEntity"
...
}
调用prepareContent()
似乎以某种方式将数组控制器锁定到特定的managedObjectContext,并在其设置为nil时导致崩溃。
如何安全地"停用"NSArrayController
,或更改其managedObjectContext?
经过大量实验,我想我发现一旦调用fetch(_:)
或preopareContent()
,NSArrayController
就会产生内存泄漏。它似乎保留了managedObjectContext
,从未释放过它。即使对控制器的所有其他引用都已释放,我也可以在内存调试器中看到泄漏的实例。
我通过用常规的NSTableViewDataSource
实现替换绑定来解决这个问题。