一个窗口中跨多个视图控制器的 Cocoa 绑定

Posted

技术标签:

【中文标题】一个窗口中跨多个视图控制器的 Cocoa 绑定【英文标题】:Cocoa binding across multiple view controllers in a window 【发布时间】:2014-10-30 07:02:03 【问题描述】:

我正在努力解决在单独文件中的视图控制器之间使用 Cocoa 绑定的案例。 我检查了一些链接以获得灵感,但仍然没有。我觉得最好发一个 问题并让我休息一下......

类似主题: Binding selection across multiple view controllers in a single window interface

Sharing an NSArrayController between multiple views in separate NIB files

我有一个主控制器MainViewController.m/.h/.xib 和两个自定义视图。

还有一个单独的视图控制器SecondViewController.m/.h/.xib。它的 xib 基本上包含一个表视图,以及一个绑定到表视图列的 ArrayController。这适用于绑定和选择等。

现在回到我的主控制器,我想从SecondViewController 访问表视图的选择索引。

到目前为止我的尝试

    在我的主 XIB 中,我在 IB 中创建了一个 ViewController,并将自定义类和 nib 文件设置为 SecondViewController

    SecondViewController 的 XIB 中创建了一个 ArrayController,其 contentArray 设置为 KVC 列表属性“lists”。如上所述,这会在表格视图中正确显示内容。

    问:如何在 MainViewController 中设置绑定,以便可以访问在 SecondViewController 中选择的对象?因为我想从我的主视图控制器中将该对象的详细信息绘制为子视图。一种在 Cocoa 教程中描述的主从界面。

【问题讨论】:

在 MainVC 中创建一个指向 SecondVC 实例的 secondVC 出口。在 SecondVC 中有一个指向 SecondVC 中的表视图的 tableView 出口。在 MainVC 中,使用 secondVC.tableView.selectionIndex 的键路径...对吗?那是很普通的东西,所以我想知道你是否想做一些更复杂的事情。 嗯,也许这很容易。所以你的意思是我需要在 secondVC 中的 tableview 插座以便稍后在我的 mainvc 中公开它?顺便说一句,没有 selectionIndex,只有 selectedRowIndexes - 这就是你的意思? 是的,语义。但是只要您的 MainVC 做一些工作来跟踪 secondVC 实例(避免使用 nil 指针),我不明白为什么您不能通过分层键路径进行绑定。 @stevesliva 我在一个沙盒项目中试过这个,mainVC 中的一个阵列控制器和第二个阵列控制器通过插座连接。我得到的只是表视图行中的左括号,用于通过插座(来自第二个 vc)连接的阵列控制器。主阵列控制器没问题。 我认为您不应该绑定或观察selectedRowIndexes - 这是NSTableView 属性。可能,您应该设置并注意对 NSArrayControllerSelection Indexes 绑定的更改,为您的第二个表格视图提供内容(请参阅下面的答案)。 【参考方案1】:

如果您想使用 Key-Value Observing 让您的 MainViewController 了解您的 SecondViewController 管理的表中所选行的更改,我认为最好的方法是是为NSArrayController 绑定Selection Indexes 设置一个值(这是为您的第二个表格视图提供内容的数组控制器)。

在您的 SecondViewController 类文件中添加如下属性:

@property (nonatomic, copy) NSIndexSet *secondTableSelectedIndexes;

现在在SecondViewController.xib 中选择相关的绿色NSArrayController 立方体,导航到它的绑定检查器并设置Selection Indexes 绑定以引用您刚刚创建的索引集属性。这是一个读写绑定。您可能永远不会自己在代码中编写它(尽管您可以根据需要),但是每次您在 SecondViewController-managed 表中选择一个新行时,该索引集都会自动更新,因此,您需要使用这个属性会观察的。

要设置观察者,无论您可以访问两个视图控制器,添加以下内容:

/* Have my main view controller watch for selection changes in my 
 * second view controller's table
 */

self.secondViewController = [[SecondTableViewController alloc] initWithNibName:@"SecondTableViewController" bundle:nil];

[self.secondViewController addObserver:self.mainViewController
       forKeyPath:@"secondTableselectedIndexes"
          options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionPrior
          context:nil];

然后可以通过在MainViewController 中实现-observeValueForKeyPath:ofObject:change:context: 来获取对secondTableSelectedIndexes 的更改。

【讨论】:

好的,我会尝试将其用于选择索引。但是将正确的字符串放入表格视图的问题仍然存在,仍然显示“(” 哪个表视图?您的SecondTableViewController xib 中有一个表格视图,MainViewController 中是否也有一个?如果您希望MainViewController 与第二个视图控制器中的选择保持同步,则无需弄乱选择索引。一旦你明确了表视图的数量,我就可以解释绑定了。 我已经在一个沙盒项目中用简单的字符串数组进行了尝试。在我的 mainvc 中,我有两个数组控制器和一个包含两列的表视图。第一列绑定到 mainarraycontroller.arrangedObjects。第二列绑定到 secondarraycontroller.arrangedObjects。 SecondArrayController 的 contentArray 绑定到 self.secondViewController.tableArray(secondViewController 是一个 IBOutlet 属性)。第一列很好,第二列显示“(”。 一个数组控制器为两个表提供数据的情况并不少见,但我没有遇到使用两个数组控制器为一个表提供内容的情况。我不确定这应该如何工作,我很想说你应该重新考虑一下——尽管我很欣赏它可能完全有可能让它工作。对于这个特定的设置,我无能为力。 好吧,两个阵列控制器的唯一目的是方便调试,我想我想多了。如果我禁用了第一列的绑定,它可以很好地显示来自第二个视图控制器的内容。谢谢!也接受您的回答,因为我现在可以在我的主 vc 中观察 selectionIndexes。下一步是对选择采取行动!

以上是关于一个窗口中跨多个视图控制器的 Cocoa 绑定的主要内容,如果未能解决你的问题,请参考以下文章

在 Angular js 中跨 2 个控制器选择的绑定值

Cocoa:根据来自 App Delegate 的输入加载不同的视图控制器

Cocoa 无法在没有托管对象上下文的情况下执行操作

如何从 Cocoa 中的窗口控制器获取当前的第一响应者?

Cocoa 加载 ViewNib

macOS Cocoa:窗口内的TabViewController,具有全尺寸内容视图