NSPersistentDocument、Storyboard 和 NSArrayController = 关闭时崩溃
NSPersistentDocument, Storyboard and NSArrayController = crash on close
问题:关闭文档window产生以下异常:
An instance 0x600000140630 of class SimpleApp.Document was deallocated while key value
observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x6100000424f0> …
<NSKeyValueObservance 0x6100000c2f40: Observer: 0x6280000c7a10, Key path: managedObjectContext, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x6100000429a0>
和
-[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release).
这是我所做的:
创建了一个新的 Xcode 项目使用:
- 使用故事板
- 创建基于文档的应用程序
- 使用核心数据
在Document.xcdatamodeld
- 创建了具有宽度和长度 2 个属性的实体(零件)
在Main.storyboard,
将一个 table 视图(基于视图)、2 个按钮(“添加”和“删除”)和一个 ArrayController 拖到视图控制器
ArrayController 模式设置为 Entity
绑定:
- table查看内容:ArrayController arrangedObjects,选择索引:ArrayController selectionIndexes
- 2 table 视图单元格绑定到 Table 单元格视图,keyPath:objectValue.width 和 objectValue.length
现在第一个问题是绑定 ArrayController managedObjectContext。我需要对 Document 子类的引用。所以我添加了
weak var document: Document? {
didSet {
print("ViewController, document didSet")
}
}
in ViewController 并将 ArrayController 托管对象上下文绑定到它 (document.managedObjectContext)。
在没有成功的情况下尝试在不同的地方设置这个 var (ViewController.viewDidLoad() ,在 NSWindowController 子类的 windowDidLoad() 中,NSDocumentController.sharedDocumentController().documentForWindow(self.window!)
总是 nil。
我在 Document.makeWindowControllers()
中使用以下方法使其工作
if let viewController = windowController.contentViewController {
viewController.setValue(self, forKey: "document")
}
所以,现在我可以创建一个新文档并保存它,打开一个保存的文档,但是一旦我关闭 window 我就会得到以前的异常。我向视图控制器和文档添加了 deinit 方法,异常发生在调用 Document.deinit
之后但在 ViewController.deinit
之前。所以看起来数组控制器仍在观察不再存在的 Document managedObjectContext。
也许我在这里遗漏了一些明显的东西,但我找不到关于如何一起使用故事板、数组控制器和文档的简单示例。顺便说一句,我也试过没有核心数据并得到了同样的异常。
已更新
我做了一个github项目
https://github.com/Miyan0/SimpleApp.git
重现崩溃的步骤:
- 创建新文档
- 保存
- 重新打开文档
- 进行任何修改
- 单击关闭框(不保存)
- 崩溃
看来解决此问题的唯一方法是将 ViewController 中的文档引用从弱更改为强。
我担心它可能会导致保留周期,但事实并非如此(根据 ViewController 和文档的打印语句和 deinit 方法)。我试图涵盖所有可能的情况,即使有时文档在关闭后未被释放 window,它最终也会在创建新文档或修改另一个文档时被释放。
问题:关闭文档window产生以下异常:
An instance 0x600000140630 of class SimpleApp.Document was deallocated while key value
observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x6100000424f0> …
<NSKeyValueObservance 0x6100000c2f40: Observer: 0x6280000c7a10, Key path: managedObjectContext, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x6100000429a0>
和
-[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release).
这是我所做的:
创建了一个新的 Xcode 项目使用:
- 使用故事板
- 创建基于文档的应用程序
- 使用核心数据
在Document.xcdatamodeld
- 创建了具有宽度和长度 2 个属性的实体(零件)
在Main.storyboard,
将一个 table 视图(基于视图)、2 个按钮(“添加”和“删除”)和一个 ArrayController 拖到视图控制器
ArrayController 模式设置为 Entity
绑定:
- table查看内容:ArrayController arrangedObjects,选择索引:ArrayController selectionIndexes
- 2 table 视图单元格绑定到 Table 单元格视图,keyPath:objectValue.width 和 objectValue.length
现在第一个问题是绑定 ArrayController managedObjectContext。我需要对 Document 子类的引用。所以我添加了
weak var document: Document? {
didSet {
print("ViewController, document didSet")
}
}
in ViewController 并将 ArrayController 托管对象上下文绑定到它 (document.managedObjectContext)。
在没有成功的情况下尝试在不同的地方设置这个 var (ViewController.viewDidLoad() ,在 NSWindowController 子类的 windowDidLoad() 中,NSDocumentController.sharedDocumentController().documentForWindow(self.window!)
总是 nil。
我在 Document.makeWindowControllers()
中使用以下方法使其工作if let viewController = windowController.contentViewController {
viewController.setValue(self, forKey: "document")
}
所以,现在我可以创建一个新文档并保存它,打开一个保存的文档,但是一旦我关闭 window 我就会得到以前的异常。我向视图控制器和文档添加了 deinit 方法,异常发生在调用 Document.deinit
之后但在 ViewController.deinit
之前。所以看起来数组控制器仍在观察不再存在的 Document managedObjectContext。
也许我在这里遗漏了一些明显的东西,但我找不到关于如何一起使用故事板、数组控制器和文档的简单示例。顺便说一句,我也试过没有核心数据并得到了同样的异常。
已更新
我做了一个github项目 https://github.com/Miyan0/SimpleApp.git
重现崩溃的步骤:
- 创建新文档
- 保存
- 重新打开文档
- 进行任何修改
- 单击关闭框(不保存)
- 崩溃
看来解决此问题的唯一方法是将 ViewController 中的文档引用从弱更改为强。
我担心它可能会导致保留周期,但事实并非如此(根据 ViewController 和文档的打印语句和 deinit 方法)。我试图涵盖所有可能的情况,即使有时文档在关闭后未被释放 window,它最终也会在创建新文档或修改另一个文档时被释放。