【问题标题】:What is the best approach for a multi window document based Cocoa app?基于多窗口文档的 Cocoa 应用程序的最佳方法是什么?
【发布时间】:2011-12-03 00:58:27
【问题描述】:

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

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

这里最好的方法是什么?

编辑:

我按照ughoavgfhw的解决方法如下:

  • 为 Locations 创建了一个新的 XIB,并添加了一个 Array Controller 来加载 Location 对象
  • 创建了一个自定义控制器ManageLocationsController 作为NSWindowController 的子类
  • 使自定义控制器成为位置 XIB 中的文件所有者
  • 将数组控制器的上下文映射到文件所有者和 keyPath document.managedObjectContext

我打开位置窗口:

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

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

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

【问题讨论】:

    标签: cocoa core-data


    【解决方案1】:

    使用自定义窗口控制器是最好的方法。窗口控制器可能无法直接访问托管对象上下文,但它可以访问文档,确实如此。您可以使用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 中的黑色小感叹号,您只需忽略它即可。 NSWindowControllerdocument 属性是使用 NSDocument 类型定义的,但 managedObjectContext 属性是由 NSPersistentDocument 子类定义的。 IB 警告您该属性可能不存在,但您知道它会存在,因此您可以忽略它。

    【讨论】:

    • 非常感谢。我已经根据您的回答编辑了带有结果的问题。
    • @Roger 抱歉,我忘记添加有关在 NSDocument 中使用自定义窗口控制器的详细信息。我现在补充一下。
    • 谢谢。这有所帮助,尽管现在我得到“这个类不符合键 managedObjectController 的键值编码”异常。我怀疑这与 keyPathsForValuesAffectingManagedObjectContext 方法有关。我需要在我的自定义控制器类中实现该方法吗?
    • 抱歉,删除最后一条评论。我打错字了,没想到。现在一切正常。再次感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多