Роль -поддержки WeePointers - PullRequest
14 голосов
/ 17 октября 2011

Apple недавно опубликовала Переход к примечаниям к выпуску ARC , документ, который объясняет ARC и решает некоторые вопросы преобразования не-ARC-кода в ARC.В этих примечаниях они упоминают следующее:

Если вы [sic] обнаружите, что должны реализовать пользовательские методы сохранения или выпуска, то вы также должны реализовать следующий метод в своем классе:

-(BOOL)supportsWeakPointers { return NO; }

Этот метод предотвратит формирование слабых указателей на ваши объекты.Настоятельно рекомендуется найти решение, которое не требует реализации собственных методов хранения и выпуска вместо этого.

Рассмотрим следующий сценарий:

  1. Объявите класс MyClass и реализуйте -supportsWeakPointers как возвращающий NO.Скажите Xcode скомпилировать соответствующий файл реализации с -fno-objc-arc.Для правильности измерения объявите класс как NS_AUTOMATED_REFCOUNT_WEAK_UNAVAILABLE и переопределите -release и -retain.

  2. В MainMenu.xib поместите объект верхнего уровня типа MyClass.

  3. В делегате приложения укажите слабое свойство IBOutlet для экземпляра MyClass:

    @property (weak) IBOutlet MyClass *myObject;
    

    и подключите его к соответствующему объекту в файле пера. В этом случаепоскольку объект является пером верхнего уровня, а владелец файла имеет тип NSApplication, этот объект создается с дополнительным счетчиком ссылок , что означает, что он должен оставаться в живых до явного выпуска.Для ARC это означает вызов CFRelease (), поскольку ARC запрещает отправку сообщения о выпуске.

У меня вопрос в два раза в три раза :

  1. Почему -supportsWeakPointers метод экземпляра вместо метода класса?Есть ли какой-нибудь случай, когда у класса могут быть экземпляры, отличающиеся разрешением слабых ссылок?

  2. -supportsWeakPointers никогда не отправляется экземпляру MyClass, созданному при загрузке файла пера;Зачем?Я проверил это, поместив в него NSLog () и добавив символическую точку останова в Xcode.Кроме того, я никогда не получаю сообщение

    cannot form weak reference to instance (0x???) of class MyClass
    

    при запуске программы.

  3. Объект nib верхнего уровня типа MyClass никогда не должен освобождатьсяво время выполнения программы, потому что моя программа никогда не выпускает его.Однако соответствующий слабый выходной сигнал равен нулю после загрузки файла пера;Зачем?Изменение свойства outlet на сильные результаты приводит к тому, что объект отличается от nil, но в этом нет необходимости. На самом деле этого не происходит;извиняюсь.Я тестировал версию, в которой был назначен новый новый объект, который в действительности не использовался, поэтому ARC правильно присвоил nil свойству.

Пример проекта, который воспроизводит эту ошибку:доступно здесь .

Я использую Xcode 4.2 с Apple LLVM Compiler 3.0 на Mac OS X версии 10.7.2.

Ответы [ 2 ]

6 голосов
/ 17 октября 2011
  1. Рассмотрим случай класса с экземпляром «shared» или «default» и другими экземплярами (например, NSFileManager).Вероятно, у вашего общего экземпляра поведение слабого указателя отличается от других выделяемых экземпляров.Есть моменты, когда разные экземпляры могут хотеть различного поведения слабых указателей.При этом, если это так, то, вероятно, что-то не совсем верно.

    (Ответ 1. Первоначально был написан Крисом Паркером . Я добавляю его в ответ Джошуа, чтобыпринятый ответ завершен.)

  2. В вашем примере изменение supportsWeakPointers на allowsWeakReference, как определено в NSObject.h, приводит к тому, что все ведет себя так, как можно было бы ожидать.Он помечен как NS_DEPRECATED, но в SDK пока что нет альтернативы.

3 голосов
/ 17 октября 2011
  1. Рассмотрим случай класса с экземплярами «shared» или «default» и другими экземплярами (например, NSFileManager). Вероятно, у вашего общего экземпляра поведение слабого указателя отличается от других выделяемых экземпляров. Есть моменты, когда разные экземпляры могут хотеть различного поведения слабых указателей. При этом, если это так, то, вероятно, что-то не совсем верно.

  2. Незнайка. :)

  3. Похоже, это может быть ошибка; Мне нужно посмотреть пример проекта, чтобы лучше понять, что происходит.

...