IBOutlet и viewDidUnload под ARC
Здесь есть аналогичный вопрос на SO здесь, однако я просто хочу прояснить то, что не было полностью объяснено там.
Я понимаю, что все делегаты и торговые точки - на самом деле любая ссылка на "родительский" объект, чтобы быть хорошим гражданином и думать о графе объектов на минуту - должна обнулять слабые ссылки. Из-за характера обнуления слабых указателей, автоматически опускающихся на нуль на счету удержания объекта ссылки, достигающего нуля, означает ли это, что установка IBOutlets на nil в viewDidUnload
теперь не нужна?
Итак, если я объявляю свой выход так:
@property (nonatomic, weak) IBOutlet UILabel *myLabel;
Имеет ли какой-либо эффект следующий код?
- (void)viewDidUnload
{
self.myLabel = nil;
[super viewDidUnload];
}
Ответы
Ответ 1
Просто сделайте немного исследований...
Как я понимаю, слабый аналогичен присваиванию, поскольку они оба являются слабыми ссылками.
Однако назначение не создает ссылку на обнуление. то есть, если объект, о котором идет речь, будет уничтожен, и вы получите доступ к этому свойству, вы получите BAD_ACCESS_EXCEPTION
.
Слабые свойства автоматически обнуляются (= nil), когда объект, на который он ссылается, уничтожен.
В обоих случаях нет необходимости устанавливать свойство на nil, так как оно не способствует сохранению счета объекта. Это необходимо при использовании сохраняемых свойств.
По-видимому, ARC также вводит новое "сильное" свойство, которое является таким же, как "сохранить"?
Выполнено исследование здесь
Ответ 2
Я провел небольшое тестирование и оказалось, что код в методе viewDidUnload
не нужен. Чтобы поддержать это, документы для viewDidUnload
действительно говорят:
К моменту вызова этого метода свойство view равно nil.
Указание на то, что слабая ссылка должна быть установлена на nil
автоматически.
Ответ 3
У меня есть некоторые эмпирические данные, подтверждающие, что IBOutlets действительно уже установлены на nil автоматически. Вот что я сделал:
- Я установил явные ivars для своих свойств IBOutlet (
@synthesize myLabel = myLabel_
), чтобы позже проверить их значения в отладчике.
- Я включил точку останова в первой строке
viewDidUnload
.
- Я организовал для
viewDidUnload
, чтобы получить вызов путем моделирования предупреждения о памяти.
- Я проверил значения явных ivars, которые были связаны с моими свойствами IBOutlet.
Явные ivars все имели nil
как их значение, тогда я попал в точку останова.
Ответ 4
Из моего понимания того, как управляемые точки управляются в ARC, если вы используете слабую ссылку, вам не нужно ничего добавлять в viewDidUnload, поскольку она уже будет равна нулю. Таким образом, это избыточно.
Однако, если у вас есть сильные розетки, которые яблоко говорит, что вы должны делать, если вы указываете на элемент верхнего уровня в nib, то вам обязательно нужно добавить соответствующую строку в viewDidUnload, чтобы их выровнять.
Ответ 5
Начиная с iOS 5 и OS X 10.7, weak
создаст автоматический указатель обнуления. Это означает, что когда выделенный объект является выпуском, указатель автоматически устанавливается на nil
(подробности см. В Обнуление слабых ссылок в ARC).
Итак, в iOS 5+ и OS X 10.7+ не рекомендуется устанавливать свойства weak
IBOutlet
в nil
вручную в методе viewDidUnload
: при выгрузке основного представления все его subviews будут выпущены, поэтому соответствующие свойства будут установлены на nil
.