Adam
Adam

Reputation: 17

How do you segue in a mac application without creating a new window?

I'm trying to segue to the bottom view controller after hitting the submit button, but when I do it creates a new window.

Storyboard

Upvotes: 1

Views: 1114

Answers (2)

Quack E. Duck
Quack E. Duck

Reputation: 678

Here is my solution, which relies extensively on this Extelligent Cocoa blog post, in particular the use of the "Tabless TabViewController". This solution avoids both having to reference the First Responder (as is done in the blog post) and having to manually instantiate View Controllers (as is discussed on the Apple Developer Forums). Segues are managed by the storyboard and achieve the same effect as a full-screen Present Modally segue would in iOS - as intended.

Please refer to the Extelligent Cocoa post linked above for the details on configuring the NSTabViewController to be tabless.

Here is the code from the parent TabViewController (make sure to check the box for "Is Initial Controller" in the Attributes Inspector):

import Cocoa

class TabViewController: NSTabViewController {
    let screens = ["Screen1": 0, "Screen2": 1]

    override func viewDidLoad() {
        super.viewDidLoad()
        K.globalVars.parentViewController = self
    }
    
    func switchScreens(to screenName: String, _ sender: Any) {
        selectedTabViewItemIndex = screens[screenName]!
    }
}

The first child ViewController:

import Cocoa

class ViewController1: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func goForward(_ sender: NSButton) {
        K.globalVars.parentViewController!.switchScreens(to: "Screen2", self)
    }
}

And the second child ViewController:

import Cocoa

class ViewController2: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func goBack(_ sender: NSButton) {
        K.globalVars.parentViewController!.switchScreens(to: "Screen1", self)
    }
}

As there doesn't seem to be a built-in way to access the parent NSTabViewController from the child NSViewControllers, it is necessary to store a reference to it somewhere in the global scope. I have done so in a Constants.swift file:

import Cocoa

struct K {
    struct globalVars {
        static var parentViewController: TabViewController?
    }
}

Here is the storyboard, shown below. When you press the Forward button on Screen 1, it transitions to Screen 2 within the same window. When you press the Back button on Screen 2, it goes back to Screen 1.

enter image description here

Upvotes: 0

caiomcg
caiomcg

Reputation: 523

That is one of the default behaviour of Cocoa segues. One solution is to close the previous window when moving through the segue.

override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    self.view.window?.close()
    //Pass data to new view
}

I have just found this tutorial and the developer creates a very interesting transition effect, take a look at the source code at the bottom of the page

Upvotes: 1

Related Questions