Должен ли я ссылаться на self.property в методе init с ARC?
Быстрый вопрос
если у меня есть свойство и ivar, объявленные с тем же именем:
в.h файле:
(Reminder*)reminder;
@property(nonatomic,strong)(Reminder*)reminder;
в файле.m я должен использовать ivar или свойство в методе init, если я использую ARC?
- (id)initWithReminder:(Reminder*)reminder_ {
self = [super init];
if (self) {
reminder = reminder_;
}
return self;
}
Или я должен использовать свойство, чтобы получить выгоду от автоматического подсчета ссылок, как это:
- (id)initWithReminder:(Reminder*)reminder_ {
self = [super init];
if (self) {
self.reminder = reminder_;
}
return self;
}
Я не уверен, в какой момент при инициализации объекта свойства становятся доступными с точечной нотацией.
3 ответа
Используйте прямой доступ в частично построенных состояниях, независимо от ARC:
- (id)initWithReminder:(Reminder*)reminder_ {
self = [super init];
if (self) {
reminder = reminder_;
// OR
reminder = [reminder_ retain];
}
return self;
}
Это потому что self.whatever
вызовет другие побочные эффекты, такие как уведомления о значении ключа (KVO), или, возможно, ваш класс реализует (явно) или переопределение подкласса setWhatever:
- и это может предоставить ваш частично инициализированный экземпляр другим API (включая его собственный), которые справедливо предполагают, что они имеют дело с полностью сконструированным объектом.
Вы можете вручную проверить, что класс способен работать в частично инициализированном состоянии, но это требует большого обслуживания и (откровенно) нецелесообразно или невозможно, когда другие люди хотят создать подкласс вашего класса. Это требует много времени и обслуживания, и при этом нет существенной выгоды, особенно если вы пытаетесь использовать этот подход в качестве соглашения.
Таким образом, единый способ, который гарантирует правильность, состоит в том, чтобы использовать прямой доступ в частично построенных состояниях и избегать использования средств доступа.
Примечание: я использую "частично построенный", потому что инициализация - только половина изображения; -dealloc
имеет подобные предостережения.
Более подробно о том, почему вы должны использовать прямой доступ в частично построенных состояниях (ARC || MRC), можно найти здесь: Инициализация свойства, точечная запись
Нет, не надо!
Вы можете найти описание, почему здесь
Также яблоко рекомендую не делать этого. Читать здесь
Я не уверен, в какой момент при инициализации объекта свойства становятся доступными с точечной нотацией.
Поскольку точечная нотация все еще является методом Objective-C (а метод C фактически находится под методом ObjC), точечная нотация или вызов метода совершенно безопасны. GIVEN, метод подготовлен для работы с базовыми типами в памяти в в каком бы состоянии они ни находились. Обычное правило об избежании использования неинициализированного (возможно) сегмента гаражной памяти все равно будет применяться. Что является самой сильной мотивацией для использования ивара в init.
Но если ваш метод (getter|setter) способен правильно использовать сегмент памяти - независимо от того, был ли он сначала записан перед чтением, - тогда непременно используйте ваш метод get в методе init. Ленивый метод получения использует преимущество предположения, что указатель, который он будет инициализировать, начинается с нуля, чтобы принять решение о выполнении инициализации. Если вы не можете принять начальное содержимое вашей памяти, то инициализация ивара может быть самым безопасным.
Почему есть правило никогда не использовать сеттеры или геттеры в инициализации, если метод способен работать правильно в этом сценарии?