在使用SWIFT4.2的Xcode 10.1中,当我在我的NSViewController中为按键事件添加一个本地监视器时,内存泄漏,它被作为最小版本(没有nib和xib)来运行。
override func loadView() {
self.view = NSView()
self.view.wantsLayer = true
}
override func viewDidLoad(){
super.viewDidLoad
NSEvent.addLocalMonitorForEvents(matching: .keyDown, handler: handler)
}
lazy var handler:(NSEvent)->NSEvent? = { [ weak self ,unowned picker = picker] event in
picker.keyDown(with: event)
return event
}这个内存泄漏没有多少信息:内存泄漏
编辑
在deinit方法中,removeMonitor被称为
deinit {
NSEvent.removeMonitor(self)
}编辑2
解决问题:
override func loadView() {
self.view = NSView()
self.view.wantsLayer = true
}
var monitor:Any? // This is essential
override func viewDidLoad(){
super.viewDidLoad
monitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown, handler: handler)
}
lazy var handler:(NSEvent)->NSEvent? = { [ weak self ,unowned picker = picker] event in
picker.keyDown(with: event)
return event
}
deinit {
NSEvent.removeMonitor(monitor)
}发布于 2019-03-11 15:07:37
来自苹果文档;
备注 对于所有匹配掩码的未来事件,都会调用监视器
Block。您必须调用removeMonitor(_:)来停止监视器。在垃圾收集下,在调用removeMonitor(_:)之前,将不会收集监视器(以及块引用的所有内容)。
这意味着监视器将继续查找匹配的事件,直到调用removeMonitor()为止。因此,您的系统正在使用额外的内存来继续查找事件,如果您从来不调用它--这可能会导致相当大的内存泄漏。正如它所说的,即使是垃圾收集,这个对象仍然被分配-因为它正在寻找可以在任何时候发生的事件(所以不能保证这将被收集)。当您希望系统停止查找事件时,请确保调用此命令。
你也可以在你的handler中做类似的事情。
您可以不修改地返回事件,创建和返回一个新的NSEvent对象,或者返回零来停止事件的分派。
https://stackoverflow.com/questions/55104573
复制相似问题