Должен ли я ссылаться на self.property в методе init с ARC? - PullRequest
50 голосов
/ 08 ноября 2011

Быстрый вопрос.

если у меня есть свойство и 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 ]

67 голосов
/ 08 ноября 2011

Использование прямого доступа в частично построенных состояниях независимо от 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), можно найти здесь: Инициализация свойства, точечная запись

5 голосов
/ 20 марта 2014

Нет, не надо!

Вы можете найти описание, почему здесь
Также Apple рекомендует не делать этого Читать здесь

0 голосов
/ 31 октября 2015

Я не уверен, в какой момент инициализации объекта свойства становятся доступными с точечной нотацией.

Поскольку точечная нотация все еще является методом Objective-C (иМетод C, фактически подчиненный методу ObjC), точечная нотация или вызов метода абсолютно безопасны. ПОДАРИТЕ, что метод подготовлен для работы с базовым типом (ами) в памяти в любом состоянии, в котором они находятся. Нормальное правило избегать использованиянеинициализированного (возможно) сегмента памяти гаража все еще будет применяться.Что является самой сильной мотивацией для использования ivar в init.

Но если ваш метод (getter | setter) способен правильно использовать сегмент памяти - независимо от того, был ли он сначала записан перед чтением -тогда непременно используйте ваш метод get в методе init.Ленивый метод получения использует преимущество предположения, что указатель, который он инициализирует, начинается с нуля, чтобы принять решение о выполнении инициализации.Если вы не можете предположить начальное содержимое вашей памяти, то инициализация ивара может быть самым безопасным курсом.

Почему существует правило никогда не использовать сеттеры или геттеры в init, если метод способен работать правильно в этом сценарии

...