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:
- Create a class which is a sub class of NSWindowController e.g. NewWindowController
- Create a window xib for NewWindowController class.
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:
- Get the list of all known applications that can open a specific file type (see
LSCopyApplicationURLsForURL
, a Core Foundation C function). - Build the menu. You can use
NSWorkspace
(and probablyURL
) to get the application icons. - 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
Navigationview Doesn't Display Correctly When Using Tabview in Swiftui
How to Make Alphabetically Section Headers in Table View with a Mutable Data Source
How to Connect Aksequencer to a Akcallbackinstrument
Avspeechutterance - Swift - Initializing with a Phrase
How to List Swift Types That Conform to Protocol Using Reflection
Swiftui 2 Firebase Push Notification
How to View Value of Swift "Let" Constant in Xcode 6 Debugger
Check for Value or Reference Type in Swift
Understanding Shorthand Closure Syntax for Map Function in Swift
Handle Swiftui and Corelocation with Mvvm-Pattern
Drawing a 3D Arc and Helix in Scenekit
Deploy App with Pre-Populated Core Data
Hstack with Sf Symbols Image Not Aligned Centered
How to Create Text File for Writing
How to Compile Latest Swift Version on Older Xcode
Swift Closures - Capturing Self as Weak
Property Observers for Uiview Bounds and Frame React Differently