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

Разница между _ и "я". в Objective-C

Есть ли разница между использованием подчеркивания и использованием ключевого слова self в Objective-C при вызове @property?

Объявление свойства:

@property (weak, nonatomic) NSString *myString;

Вызов @synthesize свойства:

@synthesize myString = _myString;

Есть ли разница, если я хочу использовать его в своем коде? Когда? В приемнике/сеттере?

self.myString = @"test";
_myString = @"test";
4b9b3361

Ответ 1

self.myString = @"test"; в точности эквивалентен записи [self setMyString:@"test"];. Оба они вызывают метод.

Вы могли бы написать этот метод самостоятельно. Это может выглядеть примерно так:

- (void)setMyString:(NSString*)newString
{
    _myString = newString;
}

Поскольку вы использовали @synthesize, вам не нужно фактически писать этот метод, вы можете просто позволить компилятору написать его для вас.

Итак, посмотрев на этот метод, похоже, что он вызывает то же самое, что просто присваивать значение переменной экземпляра, правильно? Ну, это не так просто.

Во-первых, вы можете написать свой собственный метод setter. Если вы это сделаете, ваш метод будет вызван, и он сможет делать всевозможные дополнительные вещи, а также устанавливать переменную. В этом случае использование self.myString = вызовет ваш метод, но выполнение _myString = не будет, и, следовательно, будут использоваться различные функции.

Во-вторых, если вы когда-либо используете Key Value Observing, компилятор делает некоторые очень умные трюки. За кулисами он подклассифицирует ваш класс и переопределяет ваш метод setter (независимо от того, был ли он написан вами или вами, сгенерированным синтезом), чтобы сделать вызовы willChangeValueForKey:, которые необходимы для проверки значения ключа для работы. Вам не нужно знать, как это работает (хотя это довольно интересно, если вы хотите прочитать чтение сном!), Но вам нужно знать, что если вы хотите, чтобы Key Value Observing работало автоматически, вам нужно использовать методы setter.

В-третьих, вызов метода setter, даже если вы полагаетесь на синтез для записи, дает вам гибкость в будущем. Возможно, вы захотите сделать что-то дополнительно, когда значение будет изменено, и в тот момент, когда вы обнаружите, что хотите это сделать, вы можете вручную написать метод setter - если вы привыкли всегда использовать self.myString =, тогда вы выиграли Не нужно менять остальную часть кода, чтобы начать вызов нового метода!

В-четвертых, то же самое относится к подклассам. Если кто-то другой должен был подклассифицировать ваш код, если вы используете сеттеры, тогда они могут переопределить их для настройки функциональности.

Каждый раз, когда вы напрямую обращаетесь к переменной экземпляра, вы явно не предоставляете возможность для добавления дополнительных функций в этот момент. Поскольку вы или кто-то еще захотите в будущем задействовать такую ​​функциональность, он платит за использование установщиков все время, если нет веских оснований не делать этого.

Ответ 2

Вы правы: первая версия (self.myString) вызывает синтезированный getter/setter, а вторая версия напрямую передает частную переменную-член.

Похоже, вы используете ARC, так что в этом случае это не делает такой большой разницы. Однако, если вы не используете ARC, это может иметь значение, так как назначение частного члена напрямую не приведет к автоматической логике сохранения/выпуска или копирования/выпуска, которая сгенерирована для вас, используя synthesize.

Ответ 3

_ (подчеркивание) - это просто соглашение, как описано в этом вопросе.

Если вы не префикс доступа к ресурсу с помощью self., вы напрямую обращаетесь к базовой переменной, как в c struct. В общем, вы должны делать это только в своих методах init и в специализированных аксессуарах свойств. Это позволяет использовать такие вещи, как вычисляемые свойства, и KVC для работы по назначению.