如何在同一个Mac窗口中显示新的视图控制器?

时间:2022-09-27 23:20:09

I'm fairly new to Mac development and am slightly confused by the new "storyboard" feature in Xcode 6. What I'm trying to do is segue from one view controller to another in the same window. As of right now, all the different NSViewControllerSegues present the view controller in a new window, be it a modal or just another window. What I'd like to do is just segue within the same window, much in the same way one would on iOS (though an animated transition is not crucial). How would this be achieved?

我对Mac开发很新,并且对Xcode 6中新的“故事板”功能感到有些困惑。我想要做的是在同一个窗口中从一个视图控制器到另一个视图控制器。截至目前,所有不同的NSViewControllerSegues都在一个新窗口中呈现视图控制器,无论是模态还是另一个窗口。我想做的只是在同一个窗口中进行segue,就像在iOS上一样(尽管动画过渡并不重要)。如何实现?

2 个解决方案

#1


27  

If you provide a custom segue (subclass of NSStoryboardSegue) you can get the result you are after. There are a few gotchas with this approach though:

如果您提供自定义segue(NSStoryboardSegue的子类),您可以获得您所追求的结果。但是这种方法有一些问题:

  • the custom segue will use presentViewController:animator so you will need to provide an animator object
  • 自定义segue将使用presentViewController:animator,因此您需要提供一个动画对象
  • because the presented view is not backed by a separate Window object, you may need to provide it with a custom NSView just to catch out mouse events that you don't want to propagate to the underlying NSViewController's view
  • 因为所呈现的视图不是由单独的Window对象支持,您可能需要为其提供自定义NSView,以便捕获您不希望传播到底层NSViewController视图的鼠标事件
  • there's also a Swift-only glitch regarding the custom segue's identifier property you need to watch out for.
  • 还有一个关于自定义segue标识符属性的Swift-only毛刺,需要注意。

As there doesn't seem to be much documentation about this I have made a small demo project with custom segue examples in Swift and Objective-C.

由于似乎没有太多关于此的文档,我在Swift和Objective-C中创建了一个带有自定义segue示例的小型演示项目。

如何在同一个Mac窗口中显示新的视图控制器?

I also have provided some more detail in answer to this question.

我还提供了一些回答这个问题的更多细节。

#2


1  

(Reviving this as it comes up as first relevant result on Google and I had the same problem but decided against a custom segue)

(恢复这一点,因为它出现在谷歌的第一个相关结果,我有同样的问题,但决定反对自定义segue)

While custom segues work (at least, the code given in foundry's answer worked under Swift 3; it needs updating for Swift 4), the sheer amount of work involved in writing a custom animator suggests to me that their main use case is custom animations.

虽然自定义segues工作(至少,代工厂的答案中提供的代码在Swift 3下工作;它需要更新Swift 4),编写自定义动画师所涉及的大量工作向我建议他们的主要用例是自定义动画。

The simple solution to changing the content of a window is to create an NSWindowController for your window, and to set its contentViewController to the desired viewController. This is particularly useful if you are following the typical pattern of storyboards and instantiate a new ViewController instance every time you switch.

更改窗口内容的简单解决方案是为窗口创建NSWindowController,并将其contentViewController设置为所需的viewController。如果您遵循故事板的典型模式并在每次切换时实例化一个新的ViewController实例,这将特别有用。

However.

然而。

The NSStoryboard documentation says, quite clearly in macOS, containment (rather than transition) is the more common notion for storyboards which led me to look again at the available tools.

NSStoryboard文档非常清楚地表明,在macOS中,包含(而非转换)是更常见的故事板概念,这使我再次查看可用的工具。

You could use a container view for this task, which adds a NWViewController layer instead of the NSWindowController outlined above. The solution I've gone with is to use an NSTabViewController. In the attributes inspector, set the style to 'unspecified'如何在同一个Mac窗口中显示新的视图控制器?, then select the TabView and set its style to 'tabless'. 如何在同一个Mac窗口中显示新的视图控制器?如何在同一个Mac窗口中显示新的视图控制器?

您可以为此任务使用容器视图,该视图添加NWViewController层而不是上面概述的NSWindowController。我使用的解决方案是使用NSTabViewController。在属性检查器中,将样式设置为“未指定”,然后选择TabView并将其样式设置为“tabless”。

To change tabs programatically, you set the selectedTabViewItemIndexof your TabViewController.

要以编程方式更改选项卡,请设置TabViewController的selectedTabViewItemIndex。

This solution reuses the same instance of the ViewControllers for the tab content, so that any data entered in text fields is preserved when the user switches to the other 'tab'.

此解决方案为选项卡内容重用ViewControllers的相同实例,以便在用户切换到另一个“选项卡”时保留在文本字段中输入的任何数据。

#1


27  

If you provide a custom segue (subclass of NSStoryboardSegue) you can get the result you are after. There are a few gotchas with this approach though:

如果您提供自定义segue(NSStoryboardSegue的子类),您可以获得您所追求的结果。但是这种方法有一些问题:

  • the custom segue will use presentViewController:animator so you will need to provide an animator object
  • 自定义segue将使用presentViewController:animator,因此您需要提供一个动画对象
  • because the presented view is not backed by a separate Window object, you may need to provide it with a custom NSView just to catch out mouse events that you don't want to propagate to the underlying NSViewController's view
  • 因为所呈现的视图不是由单独的Window对象支持,您可能需要为其提供自定义NSView,以便捕获您不希望传播到底层NSViewController视图的鼠标事件
  • there's also a Swift-only glitch regarding the custom segue's identifier property you need to watch out for.
  • 还有一个关于自定义segue标识符属性的Swift-only毛刺,需要注意。

As there doesn't seem to be much documentation about this I have made a small demo project with custom segue examples in Swift and Objective-C.

由于似乎没有太多关于此的文档,我在Swift和Objective-C中创建了一个带有自定义segue示例的小型演示项目。

如何在同一个Mac窗口中显示新的视图控制器?

I also have provided some more detail in answer to this question.

我还提供了一些回答这个问题的更多细节。

#2


1  

(Reviving this as it comes up as first relevant result on Google and I had the same problem but decided against a custom segue)

(恢复这一点,因为它出现在谷歌的第一个相关结果,我有同样的问题,但决定反对自定义segue)

While custom segues work (at least, the code given in foundry's answer worked under Swift 3; it needs updating for Swift 4), the sheer amount of work involved in writing a custom animator suggests to me that their main use case is custom animations.

虽然自定义segues工作(至少,代工厂的答案中提供的代码在Swift 3下工作;它需要更新Swift 4),编写自定义动画师所涉及的大量工作向我建议他们的主要用例是自定义动画。

The simple solution to changing the content of a window is to create an NSWindowController for your window, and to set its contentViewController to the desired viewController. This is particularly useful if you are following the typical pattern of storyboards and instantiate a new ViewController instance every time you switch.

更改窗口内容的简单解决方案是为窗口创建NSWindowController,并将其contentViewController设置为所需的viewController。如果您遵循故事板的典型模式并在每次切换时实例化一个新的ViewController实例,这将特别有用。

However.

然而。

The NSStoryboard documentation says, quite clearly in macOS, containment (rather than transition) is the more common notion for storyboards which led me to look again at the available tools.

NSStoryboard文档非常清楚地表明,在macOS中,包含(而非转换)是更常见的故事板概念,这使我再次查看可用的工具。

You could use a container view for this task, which adds a NWViewController layer instead of the NSWindowController outlined above. The solution I've gone with is to use an NSTabViewController. In the attributes inspector, set the style to 'unspecified'如何在同一个Mac窗口中显示新的视图控制器?, then select the TabView and set its style to 'tabless'. 如何在同一个Mac窗口中显示新的视图控制器?如何在同一个Mac窗口中显示新的视图控制器?

您可以为此任务使用容器视图,该视图添加NWViewController层而不是上面概述的NSWindowController。我使用的解决方案是使用NSTabViewController。在属性检查器中,将样式设置为“未指定”,然后选择TabView并将其样式设置为“tabless”。

To change tabs programatically, you set the selectedTabViewItemIndexof your TabViewController.

要以编程方式更改选项卡,请设置TabViewController的selectedTabViewItemIndex。

This solution reuses the same instance of the ViewControllers for the tab content, so that any data entered in text fields is preserved when the user switches to the other 'tab'.

此解决方案为选项卡内容重用ViewControllers的相同实例,以便在用户切换到另一个“选项卡”时保留在文本字段中输入的任何数据。