Подтвердить что ты не робот

Должен ли я ссылаться на 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;
}

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

4b9b3361

Ответ 1

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

Ответ 2

Нет, не стоит!

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

Ответ 3

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

Поскольку точечное обозначение по-прежнему является методом Objective-C (и методом C фактически по методу ObjC), точечная нотация или вызов метода совершенно безопасна. GIVEN метод готов к работе с базовым типом (типами) в памяти, в каком бы состоянии они ни находились. Нормальное правило об избежании использования неинициализированного (возможно) сегмента памяти гаража по-прежнему будет применяться. Что является самой сильной мотивацией для использования ивара в init.

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

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