window.windowController在windowWillClose()内为nil,但不在viewDidAppear()内

时间:2019-04-24 18:00:17

标签: swift macos nswindowcontroller

我尝试对NSWindowController内部的windowWillClose()windowShouldClose()之类的事件做出响应(是符合NSWindowDelegate的事情)。

后来,令我惊讶的是,如果我使我的contentViewController(NSViewController)符合NSWindowDelegate,我就能收到这些事件。

不幸的是,后来发现view.window?.windowControllernil中的windowWillClose()windowShouldClose(),代码:

override func viewDidAppear() {
    super.viewDidAppear()
    self.view.window?.delegate = self
    self.view.window?.windowController // not nil!
}

func windowWillClose(_ notification: Notification) {
    self.view.window?.windowController // nil!!
}

func windowShouldClose(_ sender: NSWindow) -> Bool {
    self.view.window?.windowController // nil!!
    return true
}

意识到view.window?.windowControllerviewDidAppear()中不是零之后,我想到的第二件事是Swift垃圾收集了控制器,因此我以创建另一个{的引用的方式更改了viewDidAppear() {1}}从而防止在所述对象上进行垃圾收集,代码:

windowController

我的假设被证明是正确的(我认为)。

  1. 是否也是导致我无法在NSWindowController中接收这些事件的同一问题?
  2. 还有另一种方法可以在不创建更多对象引用的情况下实现相同的目的吗?

2 个答案:

答案 0 :(得分:0)

为了发布代码,我使用“答案”选项,即使它更多是注释。

我在NSViewController中添加了

override func viewDidAppear() {
    super.viewDidAppear()
    parentWindowController = self.view.window!.windowController
    self.view.window!.delegate = self.view.window!.windowController as! S1W2WC. // The NSWC class, which conforms to NSWindowDelegate
    print(#function, "windowController", self.view.window!, self.view.window!.windowController)
}

我得到打印日志: viewDidAppear()windowController可选()

并且通知已传递。

但是如果我更改为

    override func viewDidAppear() {
        super.viewDidAppear()
//        parentWindowController = self.view.window!.windowController
        self.view.window!.delegate = self.view.window!.windowController as! S1W2WC
        print(#function, "windowController", self.view.window!, self.view.window!.windowController)
    }

通过注释parentWindowController,不再向WindowController发送通知…

编辑:我在ViewController中声明:

var parentWindowController: NSWindowController? // Helps keep a reference to the controller

答案 1 :(得分:0)

在我看来,所提出的解决方案是骇客,它们会通过创建循环引用而导致内存管理的严重问题。您绝对可以使NSWindowController的实例作为窗口的代表。正确的方法是在代码中或在Xcode的Interface Builder中将其正确连接。 here.提供了如何正确执行此操作的示例 如果未调用委托方法,则是因为接线不正确。

在Swift中必须做的另一件事是,当您在Xcode的Interface Builder中添加NSWindowController子类的名称时,请选中Inherits from Module的复选框。如果这样做失败,则不会调用任何子类方法。