Mads Gadeberg
Mads Gadeberg

Reputation: 1480

How to open a new window with its own ViewController from AppDelegate in Swift

I have made a statusBar application with a drop down. I would like to open a settingsWindow from that dropdown. I have made the settings window with its own ViewController.

The issue is that i can't figure out how to instantiate and show the settingsWindow that i have made. I have tried to follow every thread on the internet without any success.

My Viewcontroller:

class SettingsViewController: NSViewController {
   @IBOutlet var ipAddress: NSTextField!
   @IBOutlet var port: NSTextField!

   @IBAction func connect(sender: AnyObject) {}
   override func viewDidLoad() {
      super.viewDidLoad()
   }
}

My AppDelegate:

class AppDelegate: NSObject, NSApplicationDelegate {
   @IBOutlet var statusMenu: NSMenu!
   var statusItem: NSStatusItem?
   var tcpService: TcpService = TcpService()

   func applicationDidFinishLaunching(aNotification: NSNotification?) {

      let bar = NSStatusBar.systemStatusBar()

      statusItem = bar.statusItemWithLength(20)
      statusItem!.menu = statusMenu
      statusItem!.image = NSImage(byReferencingFile: NSBundle.mainBundle().pathForResource("16*16", ofType: "png"))
      statusItem!.highlightMode = true

      tcpService.initOutputStream("192.168.1.1", Port: 8888)
   }

   func applicationWillTerminate(aNotification: NSNotification?) {
      // Insert code here to tear down your application
   }
   @IBAction func openSettings(sender: AnyObject) {
      // open settings for ip and port optional port
   }
}

Upvotes: 6

Views: 5987

Answers (4)

Mannam Brahmaiah
Mannam Brahmaiah

Reputation: 2283

enum Storyboards: String {
case main = "Main"

func instantiateVC<T>(_ identifier: T.Type) -> T?  {
    let storyboard = NSStoryboard(name: rawValue, bundle: nil)
    guard let viewcontroller = storyboard.instantiateController(withIdentifier: String(describing: identifier)) as? T else { return nil}
    return viewcontroller
   }
}


var ssoLoginController: IDSSOLoginViewController?
var myWindow: NSWindow? = nil

ssoLoginController = Storyboards.main.instantiateVC(IDSSOLoginViewController.self)
myWindow = NSWindow(contentViewController: ssoLoginController!)
myWindow?.makeKeyAndOrderFront(self)
let vc = NSWindowController(window: myWindow)
vc.showWindow(self)

Upvotes: 0

Fattie
Fattie

Reputation: 12582

For 2022

  1. in your normal Main storyboard, tap to add a new window controller.

enter image description here

  1. tap precisely on the red "X", then the blue circle, and then enter "ExampleID" at the green entry.

  2. in your app's ordinary main view controller, add this

variable:

var otherWindow: NSWindowController?

function:

private func otherWindow() {
    let sb = NSStoryboard(name: "Main", bundle: nil)
    otherWindow = sb.instantiateController(
       withIdentifier: "ExampleID") as! NSWindowController
    otherWindow?.showWindow(self)
}

That's it.

Call otherWindow when you want to.

Problem:

Inevitably you will want to set up the otherWindow in a certain way, example, transparent, whatever. Unfortunately this is a whole topic in itself, but you do it like this:

private func otherWindow() {
    ... as above ...
    otherWindow?.window?.ExampleSetup()
}

and then

extension NSWindow {
    func ExampleSetup() {
        self.styleMask = .borderless
        self.collectionBehavior = [.fullScreenPrimary]
        self.level = .floating
        self.isMovable = false
        self.titleVisibility = .hidden
        // etc etc etc ..
        guard let screen = self.screen ?? NSScreen.main else {
            print("what the???")
            return
        }
        self.setFrame(screen.frame, display: true)
        // consider also .visibleFrame
    }
}

Upvotes: 0

Danny Shen
Danny Shen

Reputation: 147

in swift 3:

        var myWindow: NSWindow? = nil
        let storyboard = NSStoryboard(name: "Main",bundle: nil)
        let controller: EditorViewController = storyboard.instantiateController(withIdentifier: "editorViewController") as! ViewController
        myWindow = NSWindow(contentViewController: controller)
        myWindow?.makeKeyAndOrderFront(self)
        let vc = NSWindowController(window: myWindow)
        vc.showWindow(self)

Upvotes: 15

Georg Tuparev
Georg Tuparev

Reputation: 441

I am not 100% that I fully understand your problem, but assuming that you are using a storyboard (you should if you are starting fresh), adding few lines to your applicationDidFinishLaunching method will help:

        var myWindow: NSWindow? = nil
        let storyboard = NSStoryboard(name: "Main",bundle: nil)
        let controller: SettingsViewController = storyboard?.instantiateControllerWithIdentifier("SettingsViewController") as SettingsViewController
        myWindow = controller.window
        myWindow?.makeKeyAndOrderFront(self)

Do not forget to set the Storyboard ID in IB (in the example above to SettingsViewController)!

Upvotes: -1

Related Questions