Сбой при доступе к refcon: UnsafeMutableRawPointer? Внутри CGEventTap Callback - PullRequest
0 голосов
/ 30 октября 2018

У меня есть функция myCGEventCallback для CGEventTap, которая принимает параметр "refcon: UnsafeMutableRawPointer?".

Я передаю свой основной ViewController как указатель на обратный вызов, используя

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

Затем внутри обратного вызова я получаю доступ к ViewController, используя

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

Когда происходит событие, обратный вызов работает нормально. Однако это работает только 4 раза. Когда то же самое событие происходит в пятый раз, мое приложение вылетает, и консоль отладки просто говорит «LLDB».

Похоже, что он падает, когда я пытаюсь получить доступ к отправителю. "Sender.someFunction ()". Сбой перед запуском функции, поэтому я предполагаю, что у нее возникли проблемы с доступом к отправителю.

Это из-за плохого управления памятью? Может быть, мне нужно освободить указатель? Если да, то как и где я это сделаю?

Спасибо!

1 Ответ

0 голосов
/ 30 октября 2018

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()
    
...