我的应用程序 - 一个基于文档的核心数据应用程序 - 正在经历第二次迭代,现在需要多个窗口来管理多个模型对象。目前,它通过一个窗口和一个 Controller 来管理事件和位置。标准生成的文档类目前充当主窗口的 Controller 。
我现在需要一个单独的窗口来管理位置模型对象。为每个窗口提供一个单独的 Controller (NSWindowController)似乎是一个很好的设计,但后来我意识到这些 Controller 将无法访问托管对象上下文,而这是访问模型对象所必需的。
这里最好的方法是什么?
编辑:
我关注了ughoavgfhw解决办法如下:
- 为位置创建了一个新的 XIB,并添加了一个数组 Controller 来加载位置对象
- 创建了一个自定义 Controller
ManageLocationsController
作为NSWindowController
的子类 - 使自定义 Controller 成为位置 XIB 中的文件所有者
- 将数组 Controller 的上下文映射到文件所有者和 keyPath document.managedObjectContext
我使用以下命令打开“位置”窗口:
ManageLocationsController *aController = [[ManageLocationsController alloc] initWithWindowNibName:@"ManageLocations"];
[aController showWindow: self];
这是通过 EventDocument 完成的,EventDocument 是 XCode 生成的默认类。
映射阵列 Controller 时,这会在 keyPath 字段中留下一个圆形黑色感叹号,当我打开“位置”窗口时,它会抛出一个异常,提示“没有托管对象就无法执行操作”。显然不好。我错过了什么?
最佳答案
使用自定义窗口 Controller 是实现此目的的最佳方法。窗口 Controller 可能无法直接访问托管对象上下文,但它可以访问文档。您可以使用 windowController.document.managedObjectContext
以编程方式访问它或来自键路径 document.managedObjectContext
的绑定(bind)。如果您想模拟对托管对象上下文的直接访问,您可以创建一个从文档加载它的只读属性。
// header
@property (readonly) NSManagedObjectContext *managedObjectContext;
// implementation
- (NSManagedObjectContext *)managedObjectContext {
return self.document.managedObjectContext;
}
+ (NSSet *)keyPathsForValuesAffectingManagedObjectContext {
return [NSSet setWithObject:@"document.managedObjectContext"];
}
keyPathsForValuesAffectingManagedObjectContext
方法用于告诉键值观察系统任何观察 managedObjectContext
的对象每当属性返回的路径发生变化时,就应该通知属性发生变化。
为了使窗口 Controller 正常工作,必须使用addWindowController:
将它们添加到文档中。 。如果您在文档打开时创建多个窗口,则应覆盖 makeWindowControllers
在您的文档方法中创建窗口 Controller ,因为这将在正确的时间自动调用。如果您根据要求创建窗口 Controller ,您可以用任何您想要的方法来制作它们,只需确保将它们添加到文档中即可。
[theDocument addWindowController:myNewController];
至于IB中的黑色小感叹号,你只需忽略它即可。 document
NSWindowController
的属性(property)定义为类型NSDocument
,但是managedObjectContext
属性由 NSPersistentDocument
定义子类。 IB 警告您该属性可能不存在,但您知道它会存在,因此您可以忽略它。
关于cocoa - 基于 Cocoa 应用程序的多窗口文档的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7688137/