macos - Cocoa OS X 绑定(bind)和重要数据模型

标签 macos cocoa model-view-controller binding

该项目旨在在 Mac OS X 的 Cocoa 和 Swift 中创建一个编辑器工具,用于编辑重要的数据结构。简化的架构如下所示:

Game
    title : String
    [ Room ]

Room
    roomKey : String
    roomName : String
    roomDescription : String
    [ Object ]
    [ Exit ]

Object
    objectDescription: String

Exit 
    destinationRoomKey : String
    sourceRoomKey : String

当前的实现 - 第三次循环 - 有一个 Document.xib 文件(该应用程序是基于文档的),并且我将 NSObjectController 连接到加载的基本游戏对象通过文档,以及一个 NSArrayController 到房间的游戏对象数组。 Room 有一个 NSObjectController。我还没有完成对象或退出。

这些 View 由基本 Root View Controller 处理,当您在 View 层次结构中上下移动时,该 Controller 会交换 subview 。在根游戏状态的 View 上,单击“编辑”按钮,该按钮会在房间列表的表格 View 中滑动。单击房间行之一中的按钮会在具有自己的 Controller 的房间详细信息 View 中滑动。

这一切都运行良好。我已经连接了房间的对象 Controller ,以便它使用 Interface Builder 绑定(bind)获取 rooms 数组中选定的房间作为其对象。我可以做到这一点,因为我在一个 XIB 文件中拥有所有 View 、 View Controller 和数据模型 Controller 。

但是:现在我将游戏对象添加到此组合中,而 XIB 文件变得非常笨重。我真的觉得我想在单独的 XIB 文件中执行此操作,但是当我之前尝试时,我无法将 Controller 相互连接。我尝试手动编写代码来加载和保存数据,同时 Controller 显示和删除其 View ,但这很不稳定且容易出错。到目前为止,我得到的最优雅、最稳健的结果就是使用这种 XIB 方法。

我查看了用于绑定(bind)的编程 API,但无法理解如何让它工作,或者如何发现关键路径是什么样子。我想如果可以以编程方式进行绑定(bind),您可以将不同的部分放在不同的 XIB 中并在加载时进行绑定(bind)。但我找不到任何人成功做到这一点的例子,这似乎是一条通往疯狂的道路。

目前我对 Swift 及其与 Cocoa 和 Objective-C 的关系没有任何问题,所以如果有人有 Objective-C 或 Swift 的答案,我会很高兴听到他们。我没有把 Swift 作为这个问题的关键词,因为它不是问题的一部分。

我看过 StackOverflow answer about hierarchical models ,这就是我目前正在做的事情,所以它没有帮助。问题是,当存在多层主从结构时,这种方法会变得笨拙。

我还看到了 StackOverflow answer about sharing controllers ,这就是我之前尝试过的方法,也是我遇到那里描述的问题的地方,如果您在 NIB 中指定 Controller 对象,它将被实例化为独立对象。因此,为什么我目前采用巨额 NIB 死亡方法。

我可以将这个问题的标题设为“无法使编程绑定(bind)起作用”,但我不确定这是否是正确的方法。

肯定有人以前做过让一个不平凡的数据模型与 Cocoa 一起工作的工作吗?

最佳答案

您的辅助 NIB 应该是 View NIB,它们的所有者将是 NSViewController 的实例或自定义子类。它有一个 representedObject 属性。 NIB 及其 View Controller 类应该被视为独立的、理论上可重用的组件。也就是说,理论上,NIB 可以在多种上下文中使用来表示特定类型的对象。因此,您通常不希望连接到 UI 的其他部分或其 Controller ,除非知道该 View 正在加载以代表什么对象。

在 NIB 中,您可以使用经过 representedObject 的模型键路径绑定(bind)到文件所有者,也可以添加绑定(bind)到文件所有者 NSObjectController displayedObject,然后通过 Controller 键 selection 绑定(bind)您的 View 。

当您加载此类辅助 NIB 时,您必须将其 representedObject 设置为它应该表示的对象(取自阵列 Controller 的选择)。这应该在代码中完成,大概与决定需要加载 NIB 并执行此操作的代码相同。

如果您的 UI 设计要求详细 View 需要触发最好在更高级别处理的行为 - 例如,房间 View 需要安排退出 View 滑入窗口,但不能像它自己的 View 的 subview - 详细 View Controller 应该定义委托(delegate)协议(protocol)并实现委托(delegate)属性。例如,Room View Controller 的委托(delegate)协议(protocol)可能具有方法 -roomViewDidChangeSelectedExit:。 Room View Controller 将在其委托(delegate)上调用该方法,并传递 self。您可以将一些协调 Controller (可能是窗口 Controller )设置为详细 View 的委托(delegate)。

<小时/>

我不清楚“详细” View 和“主” View 是否同时可见。也就是说,用户是否可以在不先备份的情况下更改详细 View 要显示的对象?如果是这样,有几种方法。

您可以在加载 View 时以编程方式设置绑定(bind)。这将是加载详细 View 的 Controller 的责任。这不是详细 View Controller 的责任。它没有更高层次的视角和知识来设置绑定(bind)。不管怎样,你可以这样做:

[detailViewController bind:@"representedObject" toObject:self.arrayController withKeyPath:@"selectedObjects.firstObject" options:@{ }];

请务必在释放详细 View Controller 之前调用 -unbind:

另一种方法是使用非绑定(bind)方法简单地观察更改后的选择,并在触发的代码中设置新的representedObject。例如,如果您的主视图允许用户在 TableView 中选择一个项目,您将设置 TableView 的委托(delegate)(几乎肯定已经完成)并实现 -tableViewSelectionDidChange:。在该委托(delegate)方法中,查询新选择的项目并将其分配给 detailViewController.representedObject

关于macos - Cocoa OS X 绑定(bind)和重要数据模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27877655/

相关文章:

linux - 在不重新启动浏览器的情况下从可执行文件安装外部 Chrome 扩展

macos - 通过 iTerm2 使用 Powerlevel10k 更改 Visual Studio 代码中的终端

iphone - 如何使用 CMake 添加额外的 plist 属性?

Java 1.6.x ant 在 OSX 上构建速度较慢?

iPhone 内存管理 : a release after setting self. someProperty = nil

java - MVC Java 困惑

java - JAX-RS 是否适合作为 MVC 框架?

cocoa - 在 Cocoa 中每帧绘制一次

objective-c - 像 Numbers 中的标记文本字段

java - 使用 Spring Rest Controller