我正在像这样的情节提要中创建一个弹出式样式视图控制器
然后,我单击按钮,视图控制器就会显示出来,当我在外面的任何地方单击时,视图控制器就会“关闭”。
但是,当我再次单击该按钮时,将使用新的视图控制器实例,而前一个实例仍在运行。我已经尝试过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")
}
}
答案 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