Xcode 7中的NSToolbar使用Storyboards(NSWindowController - > NSSplitViewController)

时间:2015-06-24 10:00:27

标签: macos swift xcode7 nstoolbar nssplitviewcontroller

嗨我已经看过这个问题已经问了好几次但还没有明确的答案所以我为xcode 7和swift2创建了它(这可能会改变一些事情)。

我使用Xcode 7和Cocoa OSX Story board + swift2创建了一个项目,所以我的项目以 NSWindowController 开始,连接到NSViewController(正如预期的那样!)。我在窗口控制器中添加了 NSToolbar ,并在工具栏中添加了 NSButton 。我将我的NSViewController更改为链接到三个 NSViewController 的新 NSSplitViewController 之一并水平显示其视图 - 使用垂直分隔符 - (类似于您在优胜美地的照片应用程序或页面+)。我的最终目标是“我的工具栏”中的按钮显示并隐藏第一个分割。

我的理解是,我希望能够实现这一目标,我应该在NSSplitViewController中创建一个动作,它或多或少地改变自动布局约束的方式:How to do collapse and expand view in mac application?

然后以某种方式将此操作链接到工具栏中的NSButton ...它恰好位于NSWindowController中(远远超出层次结构中)...

我已经解决了有关NSToolbar和故事板的其他问题,但未能实现我的目标:

  • YouTube视频:Cocoa Programming L17 - NSToolbar是我发现的最接近解决问题的视频,但他的方法不适用于故事板,只创建自己的xib文件。
  • 在这个问题中:How to use NSToolBar in Xcode 6 and Storyboard?一个人建议使用第一个转发器建立链接,并期望一切都在运行时挂钩(看起来有点狡猾,而不是苹果实现它的方式我认为。 ..)。第二个人建议在NSWindowController中创建一个视图控制器变量,并从那里操纵它的属性......但同样,有点狡猾。
  • 我在这个问题中看到的最新评论似乎是解决问题的最佳方法(但仍然不如我想的那么好)是将NSObjectController添加到每个场景和场景加载时,将对象的值设置为另一个secene的控制器。这真的是最好的方式吗?如果是这样,我怎么能实现这个呢?

Apple确实在WWDC15中再次提到他们为osx和拥有视图控制器的拆分视图控制器创建了故事板,以便您可以将逻辑和工作移动到特定的视图控制器,所以我希望从我的拆分视图控制器中做所有事情,因为这是需要更改的目标。

有谁知道如何从视图控制器本身实现这一目标?我真的找不到将ToolBarItem连接到它的方法。

4 个答案:

答案 0 :(得分:3)

好的,我在几天前创造了这个问题,到目前为止还没有答案,所以我回答了我最近为克服这个问题所做的工作。

在我创建Xcode项目后,我做到了这一点:

  • 为NSSplitViewController创建子类 MySplitViewController
  • 为每个NSSplitViewItem添加了一个IBOutlet。例如:

    @IBOutlet weak var mySplitViewItem:NSSplitViewItem!

  • 为NSWindowController

  • 创建了一个子类WindowController
  • 在WindowController类中添加了一个链接到NSToolbarItem(我的按钮)的IBAction
  • 添加了一个属性,可将窗口控制器的内容设为 MySplitViewController

    var mySplitViewController:MySplitViewController {        返回self.window?.contentViewController为! MySplitViewController }

  • 现在,我可以在我创建的操作中从Window Controller访问拆分视图控制器的属性:

    mySplitViewController。 mySplitViewItem.collapsed = true

我创建了一些示例代码来执行此操作(但使用视图控制器并更改标签here的文本,以防有人想要查看具有此行为的工作项目。并且{{3}关于它:):

答案 1 :(得分:0)

所以,我正在处理同样的问题,找不到你遇到的解决方案。我读了你的帖子,并试图想象一下当我发现使用通知时我将如何实施你的解决方案。在大约30秒内,我有一个非常好的工作解决方案:

在你的windowController中添加一个IBAction来发布这样的通知

-(IBAction)toggleMasterViewClicked:(id)sender
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:nil];
}

将该动作连接到NSToolbarItem,然后在viewController中添加self作为该通知的观察者,如此

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toggleMasterView:) name:@"TestNotification" object:nil];

在您的情况下,选择器将为updateMyLabelText

我真的没有看到任何不利因素。不需要参考其他对象,也没有依赖性。为我完美无瑕地工作

答案 2 :(得分:0)

  

一个人建议使用第一个响应器创建链接,并期望在运行时连接所有内容(看起来有点狡猾而不是苹果实现它的方式,我认为......)。

我认为这个第一响应者方法实际上是正确的方法。

举个例子:

在任何视图控制器中添加类似于以下内容的内容。

@IBAction func doSomething(_ sender: AnyObject?) {
    print("Do something.")
}

这将神奇地出现在第一响应者中:

enter image description here

在您的故事板中,右键单击窗口控制器上方的橙色“第一响应者”图标,您应该在很长的列表中看到doSomething。您只需将其连接到工具栏按钮即可。

在下面的屏幕截图中,您可以看到我的“切换边栏”按钮已连接到我的第一响应者中的toggleSidebar操作。

enter image description here

我甚至不必编写此方法 - 它由NSSplitViewController提供:

    @IBAction open func toggleSidebar(_ sender: Any?)

答案 3 :(得分:0)

虽然连接 IBActions 通过使用 First Responder 或通过向场景添加“对象”,然后将其类更改为窗口的视图控制器类来工作,但这对您想要的 IBOutlets 和委托没有帮助指向视图控制器。

这里有一个解决方法:

将工具栏添加到视图控制器,而不是其窗口。这样,您可以轻松地在 View Controller Scene 中建立所有 IBOutlet 连接。我已经这样做了多年,没有发现任何问题,即使在使用 Tabs 时也是如此。

然后,您必须在代码中分配窗口的工具栏。例如。像这样:

@interface ViewController ()
    @property (weak) IBOutlet NSToolbar *toolbar; // connect this in your storyboard to the Toolbar that you moved to the View Controller Scene
@end

- (void)viewWillAppear {
    [super viewWillAppear];
    self.view.window.toolbar = self.toolbar;
}