Допустимое использование средств доступа в методах init и dealloc?
-
16-09-2019 - |
Вопрос
Сейчас я услышал об этом из нескольких источников (stackoverflow.com , cocoa-dev, документация, блоги и т.д.), Что "неправильно" использовать средства доступа и настройки (foo, setFoo:) в ваших методах init и dealloc.Я понимаю, что существует отдаленная возможность запутать другие объекты, которые наблюдают за этим свойством, если вы это сделаете.(приведен простой пример здесь)
Однако я должен сказать, что я не согласен с такой практикой по следующей причине:
Новая среда выполнения Objective-C (та, что на iPhone, и 64-разрядная среда выполнения в версии 10.5) позволяет объявлять свойства без объявляя соответствующий ivar.Например, следующий класс будет просто отлично скомпилирован на версии 10.5 или для iPhone (устройства, а не симулятора).:
@interface Foo : NSObject { }
@property (retain) id someObject;
@end
@implementation Foo
@synthesize someObject;
@end
Понимая, что приведенное выше является вполне допустимым классом Objective-C, допустим, я решаю написать инициализатор, а для целей управления памятью - метод dealloc (поскольку GC недоступен на iPhone).Все, что я когда-либо читал об инициализаторах и освобождении, привело бы меня к написанию следующих двух методов:
- (id) init {
if (self = [super init]) {
//initialize the value of someObject to nil
[self setSomeObject:nil];
}
return self;
}
- (void) dealloc {
//setting someObject to nil will release the previous value
[self setSomeObject:nil];
[super dealloc];
}
Однако, согласно документации и распространенному мнению, это "неправильно".Итак, мои вопросы заключаются в следующем:
- Как я должен инициализировать SomeObject без использования средства доступа?Вы могли бы сказать, что компилятор (или среда выполнения, или что-то еще) гарантирует, что SomeObject уже имеет значение nil, но я считаю, что полагаться на это было бы неправильным поведением.Имея приличный опыт работы в C, я видел изрядное количество ошибок из-за неправильной инициализации переменных, и это, кажется, немного отличается.
- Как я могу освободить SomeObject, если я не должен использовать средство доступа в методе dealloc?
Если ответ на любой из этих вопросов "вы не можете", то как может быть плохо использовать средства доступа в ваших методах init и dealloc?
Решение
Я понимаю, что текущее поведение 10.5, при котором синтезированные ivars недоступны напрямую, рассматривается Apple как ошибка;вы должны иметь возможность получить к нему прямой доступ, но не можете.
Следовательно, вы должны быть в состоянии сделать:
someObject = nil;
вместо того , чтобы
self.someObject = nil;
В то же время, прямое использование средства доступа - единственный способ сделать это без предоставления явного ivar.
Обновить:Эта ошибка была исправлена;теперь вы можете сделать someObject = nil
просто отлично.
Другие советы
РЕДАКТИРОВАТЬ (13 февраля 2013): Как отмечено в моем комментарии ниже, и особенно после добавления ARC, я изменил свое мнение по этому поводу.До ARC я видел много ошибок, приводящих к сбоям, из-за неправильных назначений ivar в init
.IMO, особенно при работе с младшими командами, редкие проблемы с использованием средств доступа в init
были перевешены распространенными ошибками ivar access.Поскольку ARC устранил такого рода ошибки, редкие, но возможные ошибки, которые при использовании accessor в init
могут быть более важными, и поэтому я переключился на поддержку прямого использования ivars в init
и dealloc
, и только в тех местах;средства доступа везде, где это возможно (очевидно, вы не можете использовать средства доступа внутри самого средства доступа ....)
Ответ ПЕРЕД ДУГОЙ
Я категорически не согласен с теми, кто возражает против средств доступа в -init
.Почти во всех случаях это очень хорошее место для использования средств доступа, и это избавляет от множества ошибок, которые я видел в новых кодерах Cocoa, которые неизменно не сохраняются при назначении в -init
.
-dealloc
это более жесткий вызов.У меня есть естественная склонность использовать там средства доступа (чтобы они использовались везде), но это может вызвать головную боль из-за KVO (или даже NSNotifications, если вы опубликуете уведомление об изменении в своем установщике).Тем не менее, хотя я не использую средства доступа в -dealloc
, Я считаю это очень спорным, и Apple очень непоследовательна в этом вопросе (мы знаем, что они звонят setView:
в UIViewController -dealloc
например).
В любом случае, я бы сказал, что недостаточное использование средств доступа в 100 раз увеличило количество ошибок, связанных с чрезмерным использованием.Я бы всегда ошибался в их использовании, за исключением случаев, когда есть веская причина не делать этого.