How to open a view

(Swift, macOS, Storyboards)

How to open a View with code and macOS? (a View, not a Window)

I can open a Window Controller:

var controller: NSWindowController?
if controller == nil {
let storyboard:NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
controller = storyboard.instantiateController(withIdentifier: "window1") as? NSWindowController
}
controller?.showWindow(self)

But I could not figure out how to open a View Controller. What would the be equivalent code for a View Controller in macOS?

Answered by Claude31 in 688630022

Your set up is more clear with the screen shot.

So I went to test it in code.

  • I created a new class, as SecondViewController
import Cocoa

class SecondViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
    
}
  • I created a second view, in IB (as you did), as SecondViewController, with storyboard ID SecondView
  • I created a button "Load Second View" in first view.

Its action is

@IBAction func loadSecondView(_ sender: NSButton) {

        let storyboard: NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
        let myViewController = storyboard.instantiateController(withIdentifier: "SecondView") as? SecondViewController
        self.view.window?.contentViewController = myViewController
    }

When I click in Load Second View, second view shows.

NOTE: when you answer don't just say: it gives me error. Tell exactly what the error is.

What is this ViewController ? Is it the content of the window ?

If so you could do this:

var controller: NSWindowController?
if controller == nil {
    let storyboard:NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
    controller = storyboard.instantiateController(withIdentifier: "window1") as? NSWindowController
    let myViewController = mainStoryBoard.instantiateController(withIdentifier: "myView") as? MyViewController
    controller.contentViewController = myViewController
}
controller?.showWindow(self)

See more details here: https://stackoverflow.com/questions/45119813/how-do-i-open-another-window-in-macos-in-swift-with-cocoa

I have a window controller and two views. With my code, I open view1. I try to open view2 with code.

I do not understand your code. It gives me error.

Accepted Answer

Your set up is more clear with the screen shot.

So I went to test it in code.

  • I created a new class, as SecondViewController
import Cocoa

class SecondViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
    
}
  • I created a second view, in IB (as you did), as SecondViewController, with storyboard ID SecondView
  • I created a button "Load Second View" in first view.

Its action is

@IBAction func loadSecondView(_ sender: NSButton) {

        let storyboard: NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
        let myViewController = storyboard.instantiateController(withIdentifier: "SecondView") as? SecondViewController
        self.view.window?.contentViewController = myViewController
    }

When I click in Load Second View, second view shows.

NOTE: when you answer don't just say: it gives me error. Tell exactly what the error is.

These are some of the things I tried:

var controller: NSWindowController?
@IBAction func loadSecondFromMenu(_ sender: NSButton) {
        let storyboard: NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
        let myViewController = storyboard.instantiateController(withIdentifier: "SecondView") as? SecondViewController
        //self.view.window?.contentViewController = myViewController //error: Value of type 'AppDelegate' has no member 'view'
        //controller?.contentViewController = myViewController //no error, and it does not open any window
}

You could open a new thread. But I'll try to answer here first, with a sketch of solution.

What I do is declare a global var (in a singleton in fact) to hold the windowController.

myWindowController is of a subClass of NSWindowController, with its own nib.

In the subClass MyWindowController, I have several int:

class MyWindowController: NSWindowController, NSWindowDelegate {

    override init(window: NSWindow!) {  
        // initialize what you need 
        super.init(window: window)
    }
    
    required init?(coder: (NSCoder?)) {
        // initialize what you need 
        super.init(coder: coder!)  
    }
    
    convenience init(someTag: Int) {  // Need a parameter to differentiate from basic init()
        self.init(windowNibName: NSNib.Name(rawValue: "MyNibName")) // NibName of the window
        // initialize what you need 
    }

}

The global var is initialized (in singleton) with:

myWindowController = MyWindowController(someTag: 0)  // in fact GlobalData.sharedGlobal.myWindowController =

Then the IBAction of menuItem is simply:

    @IBAction fileprivate func showMyWindow(_ sender: NSMenuItem) {
        myWindowController!.showWindow(self)   // in fact, GlobalData.sharedGlobal.myWindowController!.showWindow(self)
}

Hope that helps.

I have opened a new thread. I have been searching and trying things but still, I do not understand your sketch solution. Are you sure this is macOS and storyboards? It looks very new to me and I do not know how to learn.

How to open a view
 
 
Q