Swift MacOX-Popover segue创建多个视图控制器实例,而在关闭它们时不破坏它们

时间:2019-04-03 14:45:32

标签: swift macos segue popover nsviewcontroller

我正在像这样的情节提要中创建一个弹出式样式视图控制器

enter image description here

然后,我单击按钮,视图控制器就会显示出来,当我在外面的任何地方单击时,视图控制器就会“关闭”。

但是,当我再次单击该按钮时,将使用新的视图控制器实例,而前一个实例仍在运行。我已经尝试过deinit,但是在“关闭”视图控制器时并没有调用它。

如何在外部单击时销毁视图控制器实例,或者“显示”已创建的实例?

我在视图控制器中的代码:

class FileTransViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(updateProgress), userInfo: nil, repeats: true)
        //print(123)
        print("\(self)")
    }

    deinit {
        print("destroyed")
        if let timer = timer {
            timer.invalidate()
        }
    }

    @objc func updateProgress() {
        print("updating progress")
    }

}

2 个答案:

答案 0 :(得分:3)

该问题与弹出窗口无关。您之所以泄漏,是因为您保留了计时器,而计时器却保留了您-一个经典的保留周期。

要中断周期,必须使计时器无效。您无法在deinit中执行此操作,因为根据定义,直到您中断循环后才能调用它。 NSPopover.willCloseNotification可能是个好机会。

答案 1 :(得分:1)

正如@matt所说,保留周​​期有问题。您可以将Timer与块一起使用,在其中您可以声明weak的{​​{1}}引用

self

在这种情况下,您也不需要timer = Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { [weak self] timer in guard let self = self else { timer.invalidate() return } print("updating progress") } ,因为您将使deinit的{​​{1}}块中的计时器无效,并且也不需要变量guard如果您不想在其他地方手动使计时器无效,则只需编写else即可

timer