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