使用Storyboard连接深入分析NSSplitView出口

时间:2014-08-10 21:11:38

标签: objective-c xcode macos cocoa storyboard

我有NSSplitView来管理向下钻取的层次结构。父/左侧显示组,而子/右侧接收组选择已更改的通知,并更新以显示子项。

但是:使用故事板创建NSSplitView时,会创建3个场景:一个用于拆分视图本身,另一个用于右/左NSViewController实例

这里的问题是我有两个控制器也充当NSTableViewDataSource个项目,控制器应该有IBOutlet子< / em>控制器,以便它可以提供选择已更改的直接通知。

但是!因为这些控制器在不同的场景中,所以我无法连接它们。我也无法将它们移动到拆分视图的父场景,因为它们无法访问NSTableView个出口。 (表也不会将控制器作为代理/数据源引用。)

我需要在这里使用NSNotification吗?它看起来是间接的,多余的,我还没有在Mac上找到基于segue的方法。

enter image description here

4 个答案:

答案 0 :(得分:11)

新的NSSplitViewController和NSTabViewController类是Apple称之为容器控制器的类。您可以使用NSViewController中的新属性

获取容器内其他控制器的引用
@property (readonly) NSViewController *parentViewController
@property (copy) NSArray *childViewControllers

所以例如,如果您想从父表控制器获取对子Table控制器的引用。在父表控制器viewDidLoad中,您可以执行以下操作

myChildTableController = [self.parentViewController childViewControllers][1];
来自您的子表控制器的

或反之亦然

myParentTableController = [self.parentViewController childViewControllers][0];

答案 1 :(得分:0)

正如你所说,OS X上的故事板(以及之前的iOS),不允许你在场景之间连接IBOutlet,所以你需要以其他方式传达动作。

我将在三个控制器中的任何一个的awakeFromNib方法上配置actions / delegates属性。此时,NSSplitView及其子控制器将全部创建并连接。

如果没有多个目标对象,或者目标对象已知且已修复,我将不会使用通知,如您的情况。

答案 2 :(得分:0)

您不一定要使用NSSplitViewController。相反,只需将NSSplitView拖动到Storyboard的主视图中即可。

正如Cory在他的回答中解释的那样,新的NSSplitViewController和NSTabViewController具有访问父控制器和子控制器的方法。如果您确实希望将界面划分为不同的Storyboard场景,这将非常有用。

在您的示例中,您希望所有视图都在同一场景中,以便您可以将所有IBOutlet连接到同一个视图控制器。所以,只需使用NSSplitView,根本不用担心NSSplitViewController。

enter image description here

答案 3 :(得分:0)

我遇到了同样的问题并找到了解决方法。它不是非常优雅,它不允许您使用故事板连接插座,但它确实允许您创建与IBOutlets相同的关系。

关键是要实现一个单例类:

import Foundation
import Cocoa

class SplitViewConnector {
    static let sharedInstance = SplitViewConnector()

    var masterController:NSViewController?
    var detailController:NSViewController?
}

现在,在主控制器的awakeFromNib方法中,您可以设置主关系,同样,您可以为细节控制器设置关系。

例如,如果您的主控制器需要与您的详细控制器有直接关系,您也可以实现它。假设您的主控制器的类是YourViewController并且用于访问您的详细信息控制器的属性被称为myDetail,它将看起来像:

var masterController:YourViewController? {
    didSet {
        self.assignDirectConnections()
    }
}

var detailController:NSViewController? {
    didSet
        self.assignDirectConnections()
    }
}

func assignDirectConnections() {
    if let master = self.masterController {
         if let detail = self.detailController {
            master.myDetail = detail
         }
    }
}