OSX segue within one window

After using storyboards on iOS for some time, I'm attempting to make use of them on a Mac project.


The first oddity that I'm encountering is that "show" segues create new windows, even though there is only one window defined in my storyboard.

This seems to happen whether the segue is performed automatically through a button connection or done in code.


The documentation language is rather vague as it talks about "transition relationships" and "scenes" without defining their visual result or which objects are involved.

Is it really intended that every scene creates an extra window?


I guess the real question is: How do I achieve the expected behaviour of having a segue cause the replacement of one view controller with another while using the same window?

Replies

I can't remember if there is a built in way to do this (with segues). I've also found OS X storyboards to be very quirky.


If you just want to change the windows contentViewController you could just set the property:

self.window.contentViewController = newContentViewController;


Maybe make a custom replace segue or something, going on that, if there isn't a built in one.


If you need a navigation stack, like UINavigationController, you may have to build your own? I really can't remember. Storyboards are great on iOS but I haven't yet found them to be helpful on OS X.

>How do I achieve the expected behaviour of having a segue cause the replacement of one view controller with another while using the same window?


For replacement, you can embed the different options for what is shown into an NSTabViewController (and change the tabStyle to 'Unspecified' if you don't want user facing tab controls). Those children view controllers will be shown as different scenes and you can drive the change programmatically.


If you want to embed a view controller scene into your window content, you can use a "Container View" from IB. This lets you specify a region in the content that shoudl be represented with a view controller from a different scene.

The easiest way is to swap out the contentViewController.


// In Swift<br/>
if let controller = self.storyboard?.instantiateController(withIdentifier: "LoggedInView") as? ViewController {
self.view.window?.contentViewController = controller
}


// In Objective-C
NSViewController *controller = [[self storyboard] instantiateControllerWithIdentifier:@"LoggedInView"];
self.view.window.contentViewController = controller;


Check out a GitHub sample