Что такое @synthesize foo = _foo? - PullRequest
       24

Что такое @synthesize foo = _foo?

10 голосов
/ 02 сентября 2011

Почему нужно использовать этот префикс подчеркивания в приложении для iOS?

Ответы [ 4 ]

3 голосов
/ 16 декабря 2011

Иногда помогает понять, что происходит за сценой, чтобы понять. В основном, когда вы видите это

@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 не будет сохранен, что может привести к преждевременному сбору мусора. Хуже того, во второй строке не используется средство доступа, которое высвобождает предыдущее значение, что означает утечку памяти.

Итак, в целом, новый метод создает для вас свойство getter и setter и позволяет вам также указать имя, которое будет использоваться для переменной экземпляра, используемой для инкапсуляции.

1 голос
/ 19 декабря 2011

просто хотел добавить свои мысли ко всем приведенным выше ответам.

в моем случае я использую его в основном для защиты своих классов от несчастных случаев.

в моих .h файлах я объявляю только свойства без ivars. в файле .m я использую приведенный выше шаблон @synthesize, чтобы скрыть фактический ivar от пользователей, включая меня, чтобы они были вынуждены использовать синтезированные / динамические средства доступа, а не ивары напрямую. Вы можете использовать что угодно для своего имени ивара, а не просто подчеркнуть это. например Вы могли бы сделать:

@synthesize foo = _mySecretFoo;
@synthesize bar = oneUglyVarBecauseIHateMyBoss;

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

Я предпочитаю этот подход другим,

@property (getter=foo, setter=setFoo, ...) _mySecretFoo;
@property (getter=bar, setter=setBar, ...) oneUglyVarBecauseIHateMyBoss;

, так как это не требует частной реализации и инкапсуляции, и это просто дополнительная печать, когда Xcode может сделать то же самое для вас. Помните, свойства не такие, как у иваров! у вас может быть больше свойств, чем у иваров, или наоборот.

1 голос
/ 16 декабря 2011

Вот почему я делаю это время от времени:

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

Объявить все ваши свойства таким образом - излишне.

Надеюсь, это поможет.

0 голосов
/ 02 сентября 2011

Это соглашение по обеспечению безопасности ivar (переменных экземпляра), так что вы можете получить к нему доступ только через getter и setter.

...