首页 > 解决方案 > 访问 refcon:UnsafeMutableRawPointer 时崩溃?CGEventTap 回调内部

问题描述

我有一个用于 CGEventTap 的 myCGEventCallback 函数,它接受参数“refcon:UnsafeMutableRawPointer?”。

我将我的主 ViewController 作为指向回调的指针传递给使用

let pointer = UnsafeMutableRawPointer(Unmanaged.passRetained(self).toOpaque())

然后在回调中,我使用 ViewController 访问

let sender:ViewController = Unmanaged<T>.fromOpaque(refcon!).takeRetainedValue()

当事件发生时,回调工作正常。但是,它只能工作 4 次。当同一事件第五次发生时,我的应用程序崩溃,调试控制台只显示“LLDB”。

当我尝试访问发件人时,它似乎崩溃了。“发件人.someFunction()”。它在函数运行之前崩溃,所以我认为它在访问发件人时有问题。

这是因为内存管理不善吗?也许我需要释放指针?如果是这样,我将如何以及在哪里这样做?

谢谢!

标签: swiftcgeventtap

解决方案


passRetained(self)self将(这是您的视图控制器实例)的保留计数增加一。每次调用都会takeRetainedValue()将保留计数减一。这些调用必须适当平衡,否则对象可能会过早销毁。

在您的情况下,指针被创建一次,但在回调函数中使用了多次,您应该在回调中使用“未保留”转换:

let sender = Unmanaged<ViewController>.fromOpaque(refcon!).takeUnretainedValue()

这样就不会转移所有权。

如何创建指针有两种模式:

  • 如果保证回调仅在视图控制器的生命周期内处于活动状态,那么您可以创建指针而不保留实例:

    let pointer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
    
  • 否则,如果在回调处于活动状态时视图控制器实例应该保持活动状态,则在创建指针时保留它

    let pointer = UnsafeMutableRawPointer(Unmanaged.passRetained(self).toOpaque())
    

    并最终释放它,当回调不再活动时:

    Unmanaged<ViewController>.fromOpaque(pointer).release()
    

推荐阅读