NSEvent 泄漏导致 macOS 中的按键按下
NSEvent leak for key down in macOS
在 Xcode 10.1 和 Swift 4.2 中,当我在我的 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
}
这次内存泄漏的信息不多:Memory leak
编辑
在 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)
}
来自Apple Docs;
Note
The monitor Block
is called for all future events that match mask. You must call removeMonitor(_:)
to stop the monitor. Under garbage collection, the monitor (and everything the Block references) will not be collected until removeMonitor(_:)
is invoked.
意味着监视器将继续寻找匹配的事件,直到调用 removeMonitor()
。所以你的系统正在使用额外的内存来继续寻找事件,如果你从不调用它 - 它可能会导致相当大的内存泄漏。正如它所说,即使有垃圾收集,这个对象仍然被分配——因为它正在寻找可能随时发生的事件(所以不能保证这将被收集)。确保在您希望系统停止查找事件时调用它。
您也可以在 handler
中执行类似的操作。
You can return the event unmodified, create and return a new NSEvent object, or return nil to stop the dispatching of the event.
在 Xcode 10.1 和 Swift 4.2 中,当我在我的 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
}
这次内存泄漏的信息不多:Memory leak
编辑
在 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)
}
来自Apple Docs;
Note
The monitor
Block
is called for all future events that match mask. You must callremoveMonitor(_:)
to stop the monitor. Under garbage collection, the monitor (and everything the Block references) will not be collected untilremoveMonitor(_:)
is invoked.
意味着监视器将继续寻找匹配的事件,直到调用 removeMonitor()
。所以你的系统正在使用额外的内存来继续寻找事件,如果你从不调用它 - 它可能会导致相当大的内存泄漏。正如它所说,即使有垃圾收集,这个对象仍然被分配——因为它正在寻找可能随时发生的事件(所以不能保证这将被收集)。确保在您希望系统停止查找事件时调用它。
您也可以在 handler
中执行类似的操作。
You can return the event unmodified, create and return a new NSEvent object, or return nil to stop the dispatching of the event.