基于多窗口文档的Cocoa应用程序的最佳方法是什么?

时间:2011-10-07 13:45:00

标签: cocoa core-data

我的应用程序 - 基于文档的Core Data应用程序 - 正在进行第二次迭代,现在需要多个窗口来管理多个模型对象。目前,它通过一个窗口和一个控制器管理事件和位置。标准生成的文档类目前充当主窗口的控制器。

我现在想要一个单独的窗口来管理Locations模型对象。对于每个窗口都有一个单独的控制器(NSWindowController)似乎很好的设计,但后来我意识到这些控制器将无法访问托管对象上下文,这是访问模型对象所必需的。

这里最好的方法是什么?

编辑:

我按照以下ughoavgfhw解决方案:

  • 为地点创建了新的XIB,并添加了一个阵列控制器来加载位置对象
  • 创建了自定义控制器ManageLocationsController作为NSWindowController
  • 的子类
  • 将自定义控制器设置为位置XIB中的文件所有者
  • 将Array Controller的上下文映射到File Owner和keyPath document.managedObjectContext

我打开位置窗口:

ManageLocationsController *aController = [[ManageLocationsController alloc] initWithWindowNibName:@"ManageLocations"];
[aController showWindow: self];

这是从EventDocument完成的,它是XCode生成的默认类。

映射阵列控制器时,这会在keyPath字段中留下一个圆形的黑色感叹号,当我打开位置窗口时,它会抛出一个异常,说“无法在没有托管对象的情况下执行操作”。显然不好。我错过了什么?

1 个答案:

答案 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警告你该财产可能不在那里,但你知道它会是这样你可以忽略它。