我正在尝试使用窗口控制器显示一个窗口。 这就是我所拥有的:
NSWindow子类
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子类:
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)
}
}
当然,我也有一个包含我窗口的.xib文件。它被称为“TweetWindow.xib”。 现在,到目前为止,这应该没问题。
在我的AppDelegate.swift中,我执行以下操作:
@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);
}
}
我的问题如下: 当我尝试单击与IBAction相关联的按钮以显示窗口时,会抛出异常: var tweetWindow:TweetWindow {return self.window as! TweetWindow; }
它说致命错误:在展开可选值时意外发现nil ,因此 window 为零。
为什么窗户没有?我是否过早地尝试访问该值或什么?
以下是一些照片:
感谢。
答案 0 :(得分:5)
初始化NSWindowController
或子类的实例不加载NIB。在访问window
属性或调用showWindow()
方法(基本上间接访问window
属性)之前,不会加载NIB。在您的情况下,由于您重写了showWindow()
,因此知道在调用超类实现之前不会加载NIB非常重要。
所以,是的,在拨打超级电话之前,您在self.tweetWindow.windowWillShow()
覆盖中对showWindow()
的呼叫还为时过早。此时尚未加载NIB,因此window
插座尚未连接任何内容。
当然,您必须确保插座实际连接在NIB中,或者即使在加载NIB后也永远不会连接。但是在加载之前尝试访问它是第一个问题。
我认为您的windowWillShow()
方法是错误的,至少在实施时是这样。窗口可以以各种方式显示,而不仅仅是窗口控制器的showWindow()
方法。例如,窗口和窗口控制器之外的某些内容可以tweetWindowController.window.makeKeyAndOrderFront(nil)
。如果你真的想做这样的事情,让窗口类重写各种order...()
方法,看看窗口是否第一次被订购,如果是,请调用你的方法。
更新
您的NIB中有几处配置错误。以下是修复它们所需要做的事情:
TweetWindow
。它应该是TweetWindowController
。控制器是加载和拥有NIB的,因此File的所有者类应该是控制器类。