0

所以我正在尝试使用 CoreAudio 方法AUGraphAddRenderNotify(...),但我需要引用在通知块中创建此通知的类。因为这是一个 C 函数,所以我不能简单地添加一个[weak self] in闭包捕获。查看文档,此方法的最后一个参数允许是UnsafeMutableRawPointer在块执行期间作为第一个参数传入的。按照这个建议,这是我的代码:

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

    return noErr
}, selfPointer)

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

提前致谢!

4

1 回答 1

2

Weak references don't really work like that

Interestingly, weak references don't actually point to the target object that they model. They point to side tables, whose lifetime is different from the target object.

  • A side-table entry is allocated when the first weak reference to an object is made.
  • The creation of every weak reference increments the ref count of the side-table entry, and every destruction of a weak reference decrements it.
  • Once the target object is deallocated, the side-table entry remains in place. That way, all the weak references don't become dangling pointers.
  • After eventual deallocation of the target object, all attempts to access a weak ref to the (now-dead) cause the weak-ref to be nil-ed out (which is what you observe as a user), but also deincrements the side-table entry
  • Thus, every weak reference either needs to be destroyed (e.g. goes out of scope) or attempted to be accessed before the side table entry expires.

Since these side table entries aren't exposed to "user land" Swift code, you can't make a raw pointer to them, and so you can't really deal with weak references in this way.

Alternate ideas

I have a few ideas of what you can do instead, though I haven't tried them.

  1. You can exploit UnsafeMutableRawPointer pointer to pass in a Weak<T> wrapper, like:

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

Though I think it'll have to be a class, in this case.

  1. or for some other mechanism, such as passing in a closure (which weakly captures the object)
于 2020-04-15T18:58:29.947 回答