How to Open Another Window in MACos in Swift with Cocoa

How do I open another window in macOS in Swift with Cocoa

The Window Programming Guide is a great place to understand how windows are managed in general.

Specifically (assuming you know how to present a window controller scene in storyboards), you need somewhere to store references to the new window controllers so they’re not immediately deallocated (and disappear) when presented.

In your case, you may want to keep an array of your open detail windows in the master window controller, so that if the master goes away, the details do as well. When a detail window is open (a controller instance is created and its window shown), you’ll store its controller in the array; when closed, you remove its controller from the array so it’s deallocated.

There are a number of ways to do this, depending on how much control you want, how you want child window ownership to work, etc., but this basic pattern is usually sufficient.

To instantiate a new window controller scene from a storyboard:

var myWindowController = NSStoryboard(name: "MyStoryboardFileName", bundle: nil)?.instantiateControllerWithIdentifier("MyWindowControllerIdentifier") as MyWindowControllerClass
myWindowController?.showWindow(self)

How to open a new window on button click in Cocoa Mac Application?

If you want to create a separate class for New Window, these are the steps:

  1. Create a class which is a sub class of NSWindowController e.g. NewWindowController
  2. Create a window xib for NewWindowController class.
  3. On button click code as:

    NewWindowController *windowController = [[NewWindowController alloc] initWithWindowNibName:@"You Window XIB Name"];
    [windowController showWindow:self];

Cocoa Xcode: Open Window Controller from AppDelegate Programmatically using Swift 4 for Mac?

I find answers fast when I post a question on SO. Here's what worked for me

@objc func preferencesWindow(_ sender: Any) {
var myWindow: NSWindow? = nil
let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),bundle: nil)
let controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "preferencesWindow")) as! NSViewController
myWindow = NSWindow(contentViewController: controller)
NSApp.activate(ignoringOtherApps: true)
myWindow?.makeKeyAndOrderFront(self)
let vc = NSWindowController(window: myWindow)
vc.showWindow(self)
}

Implementing Open file with in Swift Cocoa App

Without going into details, it's pretty straight forward:

  1. Get the list of all known applications that can open a specific file type (see LSCopyApplicationURLsForURL, a Core Foundation C function).
  2. Build the menu. You can use NSWorkspace (and probably URL) to get the application icons.
  3. Use NSWorkspace.openFile(_:withApplication:) to tell the application to open the given document.

Swift open new window programmatically in macOS

The following demo creates a second window called by a method in a custom class. It may be run in Xcode by adding a 'swift.main' file and replacing AppDelegate with the following code:

import Cocoa

class Abc : NSObject {
var panel: NSPanel!

func buildWnd2() {
let _panelW : CGFloat = 200
let _panelH : CGFloat = 200

panel = NSPanel(contentRect:NSMakeRect(9300, 1300, _panelW, _panelH), styleMask:[.titled, .closable, .utilityWindow],
backing:.buffered, defer: false)
panel.isFloatingPanel = true
panel.title = "NSPanel"
panel.orderFront(nil)
}
}

let abc = Abc()

class AppDelegate: NSObject, NSApplicationDelegate {
var window:NSWindow!

@objc func myBtnAction(_ sender:AnyObject ) {
abc.buildWnd2()
}

func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}

func buildWnd() {

let _wndW : CGFloat = 400
let _wndH : CGFloat = 300

window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable, .resizable], backing:.buffered, defer:false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(window)

// **** Button **** //
let myBtn = NSButton (frame:NSMakeRect( 100, 100, 175, 30 ))
myBtn.bezelStyle = .rounded
myBtn.autoresizingMask = [.maxXMargin,.minYMargin]
myBtn.title = "Build Second Window"
myBtn.action = #selector(self.myBtnAction(_:))
window.contentView!.addSubview (myBtn)

// **** Quit btn **** //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 10, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.autoresizingMask = [.minXMargin,.maxYMargin]
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}

func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}

}
let appDelegate = AppDelegate()

// **** main.swift **** //
let app = NSApplication.shared
app.delegate = appDelegate
app.setActivationPolicy(.regular)
app.activate(ignoringOtherApps:true)
app.run()

Open New Window in Swift

After the openMyWindow() method is executed, the windowController will be released and consequently the window is nil. That's why it is not there.

You have to hold the window in you class to keep it alive, then the window will be visible.

var windowController : NSWindowController?

Cocoa Mac : creating window from AppDelegate

You need to declare your NSWindowController variable main out of applicationDidFinishLaunching method. You need also to call makeKeyAndOrderFront(nil) instead of becomeFirstResponder:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

var main: NSWindowController!

func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application

main = NSStoryboard(name : "Main", bundle: nil).instantiateController(withIdentifier: "MainWindow") as! NSWindowController
let mainVc = NSStoryboard(name:"Main", bundle: nil).instantiateController(withIdentifier: "MainViewController") as! ViewController
main.window?.contentViewController = mainVc
main.window?.makeKeyAndOrderFront(nil)

}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}


Related Topics



Leave a reply



Submit