【问题标题】:NSEvent leak for key down in macOSmacOS 中按键按下的 NSEvent 泄漏
【发布时间】:2019-03-12 05:53:42
【问题描述】:

在带有 Swift 4.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
}

这个内存泄露信息不多: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)
}

【问题讨论】:

  • 当视图控制器被关闭时你是否移除事件监视器?
  • 将图片中的代码作为文本包含进来。
  • addLocalMonitorForEvents 注意 Monitor 块被调用用于匹配掩码的所有未来事件。您必须调用 removeMonitor: 来停止监视器。在垃圾收集下,在调用 removeMonitor: 之前不会收集监视器(以及 Block 引用的所有内容)。
  • 我在 deinit 方法中使用 NSEvent.removeMonitor (self) 将其删除。这是正确的?。泄漏仍然存在

标签: swift macos cocoa nsevent


【解决方案1】:

来自Apple Docs

注意

监控器Block 被调用用于匹配掩码的所有未来事件。您必须调用removeMonitor(_:) 来停止监视器。在垃圾收集下,在调用 removeMonitor(_:) 之前不会收集监视器(以及 Block 引用的所有内容)。

这意味着监视器将继续寻找匹配的事件,直到调用removeMonitor()。因此,您的系统正在使用额外的内存来继续寻找事件,如果您从不调用它 - 它可能会导致相当大的内存泄漏。正如它所说,即使使用垃圾收集,这个对象仍然被分配 - 因为它正在寻找可能随时发生的事件(因此不能保证这将被收集)。当您希望系统停止查找事件时,请确保调用此方法。

您也可以在 handler 中执行类似操作。

你可以不加修改地返回事件,创建并返回一个新的 NSEvent 对象,或者返回 nil 来停止事件的分发。

【讨论】:

  • 我在 deinit 方法中使用 NSEvent.removeMonitor (self) 将其删除。这是正确的?。泄漏仍然存在
  • 是的,您必须通过要删除的监视器而不是自己。 self 是包含监视器的类。这不会有任何作用。
猜你喜欢
  • 2019-05-11
  • 2018-03-05
  • 1970-01-01
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
相关资源
最近更新 更多