创建一个弱的 UnsafeMutableRawPointer

Create a Weak UnsafeMutableRawPointer

所以我正在尝试使用 CoreAudio 方法 AUGraphAddRenderNotify(...) 但我需要在通知块中创建此通知的 class 的引用。因为这是一个 C 函数,所以我不能简单地添加一个 [weak self] in 闭包捕获。查看 Documentation, the last parameter of this method is allowed to be an UnsafeMutableRawPointer that will be passed in during the execution of the block as the first parameter. Following this suggestion,这是我的代码:

let selfPointer = Unmanaged.passUnretained(self).toOpaque()
AUGraphAddRenderNotify(graph, { (audioPlayerPointer, _, _, _, _, _) -> OSStatus in
    let audioPlayer = Unmanaged<AudioPlayer>.fromOpaque(audioPlayerPointer).takeUnretainedValue()
    ...

    return noErr
}, selfPointer)

这是我的问题: 我需要弄清楚如何安全地获取此指针背后的值(占 nil)。更具体地说,我想安全地访问 audioPlayer 并确保在我使用它时它没有被释放。目前,一切正常,直到 audioPlayer 被解除分配然后我的应用程序崩溃。我知道我可以使用 AUGraphRemoveRenderNotify(...) 在对象被释放之前停止通知,但不幸的是这种方法不是我正在寻找的。如何检查指针指向的对象是否已被释放?

提前致谢!

弱引用并不是那样工作的

有趣的是,弱引用实际上并不指向它们建模的目标对象。它们指向边 tables,其生命周期与目标对象不同。

  • 当第一个对对象的弱引用被创建时,一个 side-table 条目被分配。
  • 每个弱引用的创建都会增加 side-table 条目的引用计数,而每个弱引用的销毁都会减少它。
  • 一旦目标对象被解除分配,side-table 条目将保留在原位。这样,所有的弱引用都不会变成悬挂指针。
  • 在目标对象最终解除分配后,所有访问弱引用(现已失效)的尝试都会导致弱引用被 nil 淘汰(这就是您观察到的用户),但也减少了 side-table entry
  • 因此,每个弱引用要么需要被销毁(例如超出范围),要么在侧 table 条目到期之前尝试被访问。

因为这些 table 条目没有暴露给 "user land" Swift 代码,你不能为它们创建一个原始指针,所以你不能真正处理以这种方式使用弱引用。

其他想法

虽然我还没有尝试过,但我对你可以做什么有一些想法。

  1. 您可以利用 UnsafeMutableRawPointer 指针传入 Weak<T> 包装器,例如:

    struct Weak<T: AnyObject> {
        wear var object: T?
    }
    

虽然我认为在这种情况下它必须是 class

  1. 或其他一些机制,例如传入闭包(弱捕获对象)