I have created a window using XIB that I want to open when pressing a menu option (Edit->OpenWindow). I can't figure out how to open a window and have it use the XIB I made. I have been searching for a solution for 3 whole hours. So my question is: how would I make a window open when I press a button? I am using Xcode 12.5, macOS 11.2.3, Swift.
Programmatically create new window using a XIB file.
In fact doc is not very helpful here.
So I will show a complete example in a MacApp.
The window is a status bar at the bottom of screen to show help messages.
- 1. Subclass a NSWindowController
class StatusWindowController: NSWindowController {
@IBOutlet weak var helpMessageField: NSTextField! // That is the unique item in the window ; you will have more
// set nib name for the window identical to file name
override var windowNibName: NSNib.Name! { // StatusWindow.xib is the file nam for the xib
return NSNib.Name("StatusWindow")
}
override init(window: NSWindow!) {
super.init(window: window)
}
required init?(coder: (NSCoder?)) { // I had a warning here Using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead - For NSCoder!
super.init(coder: coder!) // should check in case coder is nil ?
}
// May not be needed, just in case
override func windowDidLoad() {
super.windowDidLoad()
}
}
- 2. create some global var (in fact, I created in a Singleton in the app) for the windowController instance
var helpWindowController : StatusWindowController?
var isHelpLineVisible = false
- 3. When needed, create the instance (take care not to create multiple times) ; I do it at the opening of the app to have it in place
helpWindowController = StatusWindowController()
- 4. Create Menu action showHelpAtBottom to be called by menu item:
// ancillary func, as I need to use it elsewhere in code, to show / hide the window.
func setHelpAtBottom() {
if isHelpLineVisible { // We have just made it visible by the menu action
let origin = CGPoint.zero
let size = CGSize(width: NSScreen.main!.visibleFrame.width, height: 13)
// it is a small window at bottom ; yours will be probably much larger
let frame = NSRect(origin: origin, size: size)
helpWindowController!.window!.setFrame(frame, display: true)
helpWindowController!.window!.makeKeyAndOrderFront(Global.shared.helpWindowController!.window!)
} else {
// orderOut(_:) causes the window to be removed from the screen, but does not cause it to be released.
helpWindowController!.window!.orderOut(nil)
}
}
@IBAction fileprivate func showHelpAtBottom(_ sender: NSMenuItem) {
isHelpLineVisible = !isHelpLineVisible
setHelpAtBottom()
}
- 5. Declare showHelpAtBottom as the menuAction for the menuItem (here a menu item in submenu) in IB by connecting the menuItem to the IBAction.
Hope that helps.
I forgot something:
- 6. The window in IB is declared of class StatusWindow
- 7. class is defined as:
class StatusWindow: NSWindow {
func hideStatusWindow() {
self.orderOut(nil)
}
}