Создать слабый UnsafeMutableRawPointer - PullRequest
0 голосов
/ 15 апреля 2020

Итак, я пытаюсь использовать метод 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(...), чтобы остановить уведомление до того, как объект будет освобожден, но, к сожалению, этот метод не тот, который я ищу. Как я могу проверить, был ли освобожден объект, на который указывает указатель?

Заранее спасибо!

1 Ответ

2 голосов
/ 15 апреля 2020

Слабые ссылки на самом деле не работают так

Интересно, что слабые ссылки на самом деле не указывают на целевой объект, который они моделируют. Они указывают на боковые таблицы, время жизни которых отличается от целевого объекта.

  • Запись боковой таблицы выделяется при создании первой слабой ссылки на объект.
  • Создание каждого слабого эталона увеличивает счетчик ссылок записи вспомогательного стола, а каждое уничтожение слабого эталона уменьшает его.
  • Как только целевой объект освобожден, запись в боковом столе остается на месте. Таким образом, все слабые ссылки не становятся висячими указателями.
  • После возможного освобождения целевого объекта все попытки получить доступ к слабому рефу (теперь мертвому) приводят к тому, что слабый реф становится nil -ed out (это то, что вы наблюдаете как пользователь), но также деинкрементирует запись в боковой таблице
  • Таким образом, каждая слабая ссылка либо должна быть уничтожена (например, выходит из области видимости), либо предпринята попытка быть доступным до истечения срока действия записи в боковой таблице.

Поскольку эти записи в боковой таблице не открыты для кода Swift "пользовательского уровня", вы не можете сделать необработанный указатель на них, и поэтому вы можете На самом деле я не имею дело со слабыми ссылками.

Альтернативные идеи

У меня есть несколько идей о том, что вы можете сделать вместо этого, хотя я не пробовал их.

  1. Вы можете использовать указатель UnsafeMutableRawPointer для передачи в Weak<T> оболочку, например:

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

Хотя я думаю, что это должно быть class, в данном случае.

или для какого-либо другого механизма, такого как прохождение в замыкании (которое слабо захватывает объект)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...