Зачем нужен этот префикс нижнего подчеркивания в приложении iOS?
Что такое @synthesize foo = _foo?
Ответ 1
Иногда это помогает понять, что происходит за кулисами, чтобы понять. В основном, когда вы видите это
@property (nonatomic, retain) Foo *foo;
С этим в реализации
@synthesize foo=_foo;
Это синтаксический сахар для следующего, что означает, что компилятор в основном генерирует этот код для вас
Foo *foo = nil;
-(Foo *) foo {
return _foo;
}
-(void) setFoo:(Foo *)val {
if( _foo != val ) {
[_foo release];
_foo = [val retain];
}
}
Таким образом, когда вы ссылаетесь на публичное свойство, вы попадаете в него через сгенерированные аксессуары self.foo, и если вы хотите обратиться к переменной экземпляра внутри вашего класса, вы можете обратиться к _foo. До XCode четыре было легко запутаться между ними. Вы могли бы сделать что-то вроде
self.foo = foo1;
foo = foo2;
Это было совершенно законно и могло вызвать проблемы на уровне пары. Вторая строка не использует аксессуар, поэтому foo2 не будет сохранен, что может привести к тому, что он будет поднят сбором мусора досрочно. Хуже того, вторая строка не использует аксессуар, который высвобождает любое предыдущее значение, означающее, что это приведет к утечке памяти.
Таким образом, новая методика создает свойство getter и setter для вашего свойства и позволяет также указать имя, которое будет использоваться для переменной экземпляра, используемой для инкапсуляции.
Ответ 2
Вот почему я делаю это время от времени:
Если я хочу делать ленивую загрузку по свойству, я, как правило, подчеркиваю свой ivar, чтобы выполнялась работа по загрузке нужных данных с внешнего сервера/сохраненного файла/что-то-вы только загружались в первый раз, Например:
- (NSMutableArray *)recentHistory;
{
if (_recentHistory == nil)
{
// Get it and set it, otherwise no work is needed... hooray!
}
return _recentHistory;
}
Таким образом, здесь вызов свойства [instanceOfClass recentHistory] (или instanceOfClass.recentHistory) проверяет ivar, чтобы узнать, нужно ли ему загружать данные или просто возвращать уже загруженные данные.
Это избыток, чтобы объявить все ваши свойства таким образом.
Надеюсь, что это поможет.
Ответ 3
просто хотел добавить мои мысли ко всем приведенным выше ответам.
в моем случае, я использую его в основном для того, чтобы мои классы были в безопасности от несчастных случаев.
в моих .h файлах, я объявляю только свойства без ivars. в .m файле, я использую вышеприведенный шаблон @synthesize
, чтобы скрыть фактический ivar от пользователей, включая меня, для принудительного использования синтезированных/динамических аксессуаров, а не иначе ivars напрямую. вы можете использовать что-нибудь для своего имени ivar, а не просто подчеркивать его. например вы можете сделать:
@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;
таким образом, ваш босс будет видеть только бар, и вы найдете гораздо проще и, следовательно, более безопасным, использовать аксессуар для бара - используете ли вы точечную нотацию или сообщения.
Я предпочитаю этот подход по сравнению с другим,
@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;
поскольку это не обеспечивает принудительное выполнение частной инкапсуляции и инкапсуляции, и это просто дополнительная набрав, когда Xcode может сделать то же самое для вас. одна вещь, чтобы помнить, свойства не такие же, как ивары! вы можете иметь больше свойств, чем ivars, или наоборот.
Ответ 4
это соглашение, чтобы сохранить ivar (переменные экземпляра) в безопасности, поэтому вы можете получить доступ к нему только через getter и setter.