11

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

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

我的理解是,我希望要实现这一点,我应该在 NSSplitViewController 中创建一个动作,以或多或少地改变自动布局约束的方式:如何在 Mac 中折叠和展开视图应用?.

然后以某种方式将此操作链接到工具栏中的 NSButton ......它恰好在 NSWindowController 中(在层次结构中很远并且被隔离)......

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

  • YouTube 视频:Cocoa Programming L17 - NSToolbar这是我发现的最接近解决问题的方法,但他的方法不适用于情节提要,只能创建您自己的 xib 文件。
  • 在这个问题中:如何在 Xcode 6 和 Storyboard 中使用 NSToolBar?一个人建议使用第一个响应器建立链接,并期望一切都在运行时连接(这看起来有点狡猾,而不是我认为苹果会实现它的方式......)。第二个人建议在 NSWindowController 中创建一个视图控制器变量并从那里操作它的属性......但同样,也有点狡猾。

  • 我在那个问题中看到的一个最新评论似乎是解决问题的最佳方法(但仍然不如我想的那么好)是将 NSObjectController 添加到每个场景的停靠栏,当场景加载时,设置值的对象到另一个 secene 的控制器。这真的是最好的前进方式吗?如果是这样,我怎么能做到这一点?

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

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

4

4 回答 4

3

好的,几天前我已经创建了这个问题,到目前为止还没有答案,所以我已经回答了我最近为克服这个问题所做的事情。

在我创建了我的 Xcode 项目后,我这样做了:

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

    @IBOutlet 弱 var mySplitViewItem:NSSplitViewItem!

  • 为 NSWindowController 创建了一个子类 WindowController

  • 在 WindowController 类中添加了一个链接到 NSToolbarItem(我的按钮)的 IBAction
  • 添加了一个属性,该属性将 Window Controller 的内容作为MySplitViewController

    var mySplitViewController: MySplitViewController { return self.window?.contentViewController as!我的SplitViewController }

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

    我的SplitViewController。mySplitViewItem.collapsed = true

我创建了一些示例代码来执行此操作(但使用视图控制器并在此处更改标签的文本,以防万一有人想查看具有此行为的工作项目。还有一篇关于它的博客文章:)

于 2015-07-11T08:12:26.550 回答
2

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

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

举个例子:

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

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

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

在此处输入图像描述

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

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

在此处输入图像描述

我什至不必编写这个方法——它由以下提供NSSplitViewController

    @IBAction open func toggleSidebar(_ sender: Any?)
于 2017-05-11T07:01:49.293 回答
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

我真的看不出这里有什么缺点。不需要引用其他对象,没有依赖关系。对我来说完美无缺

于 2016-02-07T00:49:02.113 回答
0

虽然 connectiong 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;
}
于 2021-07-06T14:24:49.713 回答