【问题标题】:self.window is always nilself.window 始终为零
【发布时间】:2015-08-10 16:41:46
【问题描述】:

我目前正在尝试使用窗口控制器显示一个窗口。 这就是我所拥有的:

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!推文窗口; }

它说 fatal error: unexpectedly found nil while unwrapping an Optional value,所以 window 是 nil。

为什么 window nil 在那里?我是否试图过早地访问该值或其他什么?

这里有一些照片:

谢谢。

【问题讨论】:

    标签: macos swift


    【解决方案1】:

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

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

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

    我认为您的 windowWillShow() 方法是错误的,至少在实施时是这样。窗口可以以多种方式显示,而不仅仅是通过窗口控制器的showWindow() 方法。例如,窗口和窗口控制器之外的东西可以做tweetWindowController.window.makeKeyAndOrderFront(nil)。如果你真的想做这样的事情,让窗口类覆盖各种order...() 方法,看看窗口是否是第一次被订购,如果是,调用你的方法。


    更新:

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

    • 断开当前从文件所有者的“代表”出口到窗口的连接。点击您发布的任一屏幕截图中的“x”按钮。
    • 更改文件所有者的类别。目前是TweetWindow。应该是TweetWindowController。控制器是加载并拥有NIB的,所以File's Owner的类应该是控制器类。
    • 将File's Owner的“window”出口连接到window。
    • 将窗口的“委托”出口连接到文件的所有者。

    【讨论】:

    • 我删除了被覆盖的函数(“showWindow”),但它仍然在“windowDidLoad”中抛出异常。似乎插座出现故障或类似情况。我将代理连接到文件的所有者,但没有任何更改。
    • "我将代理连接到文件的所有者" 重要的不是窗口的代理连接到文件的所有者。就是 File's Owner 的窗口插座连接到窗口。其他要检查的事项:NIB 窗口中 File's Owner 的类是TweetWindowController,对吗?您是否在 NIB 中实例化了该类的另一个实例?也就是说,您是否将“对象”拖入NIB并将其类设置为TweetWindowController?如果是这样,请将其从 NIB 中删除。
    • 我更改了它,以便文件所有者的出口代表现在引用窗口。文件所有者的类别是“TweetWindow”。我用 TweetWindowController 试过了,但仍然出现异常。但这无论如何都没有意义,不是吗?我没有其他对象在我的 NIB 中将“TweetWindowController”设置为类,所以我认为这不可能是异常的来源。
    • 除了applicationDidFinishLaunching() 之外,您的代码中是否还有其他地方可以实例化TweetWindowController?您可能需要使用当前代码、NIB 文档大纲的屏幕截图、文件所有者的身份检查器以及文件所有者和窗口的连接检查器来更新您的问题。
    • 我只在我的程序中创建它的一个实例。我更新了上面的问题并添加了一些照片。
    猜你喜欢
    • 2016-05-02
    • 2012-01-16
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    相关资源
    最近更新 更多