self.window总是零

Dom*_* B. 8 macos swift

我正在尝试显示一个带有窗口控制器的窗口.这就是我所拥有的:

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();
}
}
Run Code Online (Sandbox Code Playgroud)

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)
}
}
Run Code Online (Sandbox Code Playgroud)

当然,我也有一个包含我窗口的.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);
}
}
Run Code Online (Sandbox Code Playgroud)

我的问题如下:当我尝试点击与IBAction相关联的按钮以显示窗口时,会抛出异常: var tweetWindow:TweetWindow {return self.window as!TweetWindow; }

它表示致命错误:在展开Optional值时意外发现nil,因此窗口为零.

为什么那里的窗户没有?我是想过早地获取价值还是什么?

这是一些照片:

窗口

文件的所有者

文件的所有者身份检查员

谢谢.

Ken*_*ses 5

初始化实例NSWindowController或子类并不会加载NIB。在window访问该属性或showWindow()调用该方法(基本上是window间接访问该属性)之前,不会加载NIB 。在您的情况下,由于您要覆盖showWindow(),因此必须知道在调用超类实现之前不会加载NIB,这一点很重要。

因此,是的,在调用super之前,您self.tweetWindow.windowWillShow()showWindow()覆盖中的调用为时过早。NIB当时尚未加载,因此window插座尚未连接任何东西。

当然,您必须确保在NIB中实际连接了插座,或者即使在装入NIB之后也不会连接插座。但是尝试在加载之前访问它是第一个问题。

我认为您的windowWillShow()方法至少在实施时被误导了。可以通过多种方式显示窗口,而不仅仅是通过窗口控制器的showWindow()方法。例如,窗口和窗口控制器外部都可以执行操作tweetWindowController.window.makeKeyAndOrderFront(nil)。如果您确实想做这样的事情,请让窗口类重写各种order...()方法以查看是否第一次订购了该窗口,如果是,则调用您的方法。


更新:

您的NIB中有几处配置错误。您需要执行以下操作来修复它们:

  • 断开当前连接,从文件所有者的“代理”出口到窗口。单击在您发布的任一屏幕截图中看到的“ x”按钮。
  • 更改文件所有者的类。现在是TweetWindow。应该是TweetWindowController。控制器负责加载和拥有NIB,因此文件所有者的类应为控制器类。
  • 将文件所有者的“窗口”出口连接到窗口。
  • 将窗口的“代理”出口连接到文件的所有者。