Что такое @synthesize foo = _foo?
Зачем нужен этот префикс подчеркивания в приложении для iOS?
4 ответа
Иногда это помогает увидеть, что происходит за сценой, чтобы понять. В основном, когда вы видите это
@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 4 было легко запутаться между ними. Вы могли бы сделать что-то вроде
self.foo = foo1;
foo = foo2;
Это было совершенно законно и могло вызвать проблемы на нескольких уровнях. Вторая строка не использует метод доступа, поэтому foo2 не будет сохранен, что может привести к преждевременному сбору мусора. Хуже того, во второй строке не используется средство доступа, которое высвобождает предыдущее значение, что означает утечку памяти.
Итак, в итоге, новый метод создает метод получения и установки для вашего свойства и позволяет вам также указать имя, которое будет использоваться для переменной экземпляра, используемой для инкапсуляции.
Вот почему я делаю это время от времени:
Если я хочу выполнить отложенную загрузку свойства, я обычно подчеркиваю свой ivar, чтобы работа, выполняемая для загрузки требуемых данных с внутреннего сервера / сохраненного файла /what-have-you, загружалась только в первый раз. Например:
- (NSMutableArray *)recentHistory;
{
if (_recentHistory == nil)
{
// Get it and set it, otherwise no work is needed... hooray!
}
return _recentHistory;
}
Таким образом, здесь вызовы свойства [instanceOfClass RecentHistory] (или instanceOfClass.recentHistory) проверят ивар на предмет необходимости загрузки данных или просто возврата уже загруженных данных.
Это слишком сложно объявить все ваши свойства таким образом.
Надеюсь, это поможет.
Просто хотел добавить свои мысли ко всем вышеперечисленным ответам.
в моем случае я использую его, главным образом, для защиты моих классов от несчастных случаев.
в моих.h файлах я объявляю только свойства без ivars. в.m файле я использую выше @synthesize
шаблон, позволяющий скрыть фактический ivar от пользователей, включая меня, чтобы быть вынужденным использовать синтезированные / динамические средства доступа, а не напрямую ивара напрямую. Вы можете использовать что угодно для своего имени ивара, а не просто подчеркнуть это. например, вы могли бы сделать:
@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;
таким образом, ваш босс будет видеть только панель, и вам будет гораздо проще и, следовательно, безопаснее использовать аксессор панели - будь вы используете точечную запись или сообщения.
я предпочитаю этот подход другим,
@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;
поскольку это не требует частной реализации и инкапсуляции, и это просто дополнительная типизация, когда XCode может сделать то же самое для вас. Помните, что свойства не такие, как у иваров! у вас может быть больше свойств, чем у иваров, или наоборот.
Это соглашение о том, чтобы сохранить ivar (переменные экземпляра) в безопасности, так что вы можете получить к нему доступ только через getter и setter.