RookiePro RookiePro - 4 years ago 1290
Swift Question

NSWindowController without a nib file in Swift

I am a beginner Cocoa developer. The team I have been hired by does OS X development in Swift without using nib files (except apparently for the main menu). So, I am trying to learn this before I join the team. Here is what I have so far:

I created a new OS X project without storyboards. I created a new file called MainWindowController.swift, made it a subclass of NSWindowController and did not create a xib/nib file. I also made the MainWindowController implement the NSWindowDelegate protocol

In the MainMenu.xib file, I deleted the window that came with the app by default but I kept the main menu.

In the app delegate, I deleted the default outlet for the window.

I then created an NSWindow programmatically in the app delegate. I want the MainWindowController to be the delegate of this window. This is how my AppDelegate looks:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

let newWindow = NSWindow(contentRect: NSMakeRect(100, 100, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2), styleMask: NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask, backing: NSBackingStoreType.Buffered, `defer`: false)

func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
let wc = MainWindowController.init(window: newWindow)
wc.showWindow(self)
}

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

}


As you can see, I am creating a window object and then, in the applicationDidFinishLaunching method, I initialize my custom NSWindowController with that window and then show that window. I am not sure if any of this is correct.

Then, within my custom NSWindowController, I am making 'self' the delegate of the window using 'self.window?.delegate = self'. This is how my MainWindowController looks

import Cocoa

class MainWindowController: NSWindowController, NSWindowDelegate {

override func windowDidLoad() {
super.windowDidLoad()

self.window?.delegate = self

// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.

}

func windowDidMiniaturize(notification: NSNotification) {
print("Window minimized")
}

func windowWillClose(notification: NSNotification) {
print("Window closing")
}
}


As you can see, I have a couple of test prints in the delegate methods.

When I run the app, the window does show. However, when I minimize or close the window, nothing gets printed to the console. So, it appears that the delegate has not been set correctly for the window.

What is the correct way to do things?

Answer Source

In your AppDelegate class, instead of storing your window in a property, you want to store your window controller. The way you have it now, there is no strong reference to the window controller, so it is destroyed when applicationDidFinishLaunching finishes executing. The window controller will keep a strong reference to its window, so you should not need to keep a separate strong reference to the window. I would also set the window's delegate in applicationDidFinishLaunching as well - I'm not sure if windowDidLoad is called when you are not using a nib.

I think your AppDelegate class should look something like this:

class AppDelegate: NSObject, NSApplicationDelegate {

    let windowController = MainWindowController(
        window: NSWindow(contentRect: NSMakeRect(100, 100, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2), 
        styleMask: NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask, 
        backing: NSBackingStoreType.Buffered, 
       `defer`: false))

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        windowController.window?.delegate = windowController
        windowController.showWindow(self)
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download