I'm currently trying to display a window with a window controller. That is what I have:
NSWindow subclass
import Cocoa
import CoreLocation
class TweetWindow: NSWindow {
var locationManager: CLLocationManager!
var geoCoder: CLGeocoder!
@IBAction func tweetButtonPressed(sender:NSButton) {
}
func initialize() {
self.titleVisibility = NSWindowTitleVisibility.Hidden;
self.locationManager = CLLocationManager();
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = 10;
self.geoCoder = CLGeocoder();
}
func windowWillShow() {
if !self.visible {
let systemAppearanceName = (NSUserDefaults.standardUserDefaults().stringForKey("AppleInterfaceStyle") ?? "Light").lowercaseString;
let systemAppearance = systemAppearanceName == "dark" ? NSAppearance(named: NSAppearanceNameVibrantDark) : NSAppearance(named: NSAppearanceNameVibrantLight);
self.appearance = systemAppearance;
self.locationManager.startUpdatingLocation();
}
}
func windowWillClose() {
self.locationManager.stopUpdatingLocation();
}
}
NSWindowController subclass:
import Cocoa
class TweetWindowController: NSWindowController {
var tweetWindow: TweetWindow { return self.window as! TweetWindow; }
override func windowDidLoad() {
super.windowDidLoad()
self.tweetWindow.initialize()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
override func showWindow(sender: AnyObject?) {
self.tweetWindow.windowWillShow()
super.showWindow(sender)
}
}
Of course, I've got a .xib-file, too, that contains my window. It is called "TweetWindow.xib". Now, so far this should be ok.
In my AppDelegate.swift I do the following:
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var tweetWindowController:TweetWindowController!;
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
tweetWindowController = TweetWindowController(windowNibName: "TweetWindow");
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
func showTweetWindowInternal() {
NSApp.activateIgnoringOtherApps(true);
tweetWindowController.showWindow(nil);
}
@IBAction func showTweetWindow(sender: AnyObject) {
showTweetWindowInternal();
}
@IBAction func quitApp(sender: AnyObject) {
NSApplication.sharedApplication().terminate(self);
}
}
My problem is the following: When I try to click on my button that is associated with the IBAction down there to show the window, an exception is thrown here: var tweetWindow: TweetWindow { return self.window as! TweetWindow; }
It says fatal error: unexpectedly found nil while unwrapping an Optional value, so window is nil.
Why is window nil there? Am I trying to access the value too early or something?
Here are some photos:
Thanks.
Initializing an instance of NSWindowController
or a subclass does not load the NIB. The NIB is not loaded until the window
property is accessed or the showWindow()
method is called (which basically accesses the window
property indirectly). In your case, since you're overriding showWindow()
, it's important to know that the NIB is not loaded until the superclass implementation is called.
So, yes, your call to self.tweetWindow.windowWillShow()
in your showWindow()
override, before calling through to super, is too early. The NIB has not been loaded at that point, so the window
outlet has not been connected to anything.
Of course, you have to make sure the outlet is actually connected in the NIB or it will never be connected, even after the NIB is loaded. But trying to access it before it's loaded is the first problem.
I think your windowWillShow()
method is misguided, at least as implemented. The window can be shown in various ways, not just by the window controller's showWindow()
method. For example, something outside of both the window and the window controller could do tweetWindowController.window.makeKeyAndOrderFront(nil)
. If you really want to do something like this, have the window class override the various order...()
methods to see if the window is being ordered in for the first time and, if so, call your method.
Update:
You have several things misconfigured in your NIB. Here's what you need to do to fix them:
TweetWindow
. It should be TweetWindowController
. The controller is what loads and owns the NIB, so the class of File's Owner should be the controller class.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With