在xcode 10.1中使用swift 4.2,当我在nsviewController中添加键入事件的本地监视器时,我的内存泄漏,它可以作为最小版本(无需NIB和NIB和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方法中称为
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)
}
来自Apple Docs;
注意
监视器
Block
用于与蒙版匹配的所有未来事件。您必须致电removeMonitor(_:)
以停止监视器。在垃圾收集下,在调用removeMonitor(_:)
之前,将不会收集监视器(以及所有块引用)。
这意味着监视器将继续寻找匹配事件,直到调用removeMonitor()
为止。因此,您的系统正在使用额外的内存来继续寻找事件,如果您从未调用此事件 - 可能会导致内存相当大。正如它所说的,即使收集垃圾,该对象仍然是分配的 - 因为它正在寻找可以随时发生的事件(因此不能保证将收集这一点)。当您希望系统停止寻找事件时,请确保您致电。
您也可以在handler
中做类似的事情。
您可以将事件返回未修改,创建并返回新的NSEVENT对象,或返回零以停止派遣事件。