Почему мне нужно писать @synthesize, когда я предоставляю геттер и сеттер?

Так что автосинтез свойств — это круто. Однако, когда вы предоставляете и геттер, и сеттер, вы получаете ошибку.

@property (strong, nonatomic) NSArray *testArray;

- (NSArray *)testArray {
    return _testArray;
}

- (void)setTestArray:(NSArray *)testArray {
    _testArray = testArray;
}

Ошибка: Use of undeclared identifier '_testArray'.

Добавление @synthesize testArray = _testArray; решает проблему. Мне просто интересно, почему это?


person Kevin Renskers    schedule 16.10.2012    source источник
comment
Кажется, вы не объявляете сам ивар. Кстати, это совершенно не связано с Xcode. Это не имело бы значения, если бы вы использовали Eclipse или nano и make для написания своих программ.   -  person    schedule 16.10.2012
comment
Там находится @property (и вопрос об автоматически синтезируемых свойствах). Кроме того, он отлично работает, когда вы реализуете только либо геттер, либо сеттер, он терпит неудачу только тогда, когда вы делаете оба.   -  person Kevin Renskers    schedule 16.10.2012
comment
@property объявляет iVar   -  person Tim Reddy    schedule 16.10.2012


Ответы (3)


Когда вы предоставляете и геттер, и сеттер, часто вообще не нужна переменная экземпляра, то есть когда вы просто пересылаете эти сообщения или сохраняете данные в других местах.

Как только один из них отсутствует, ивар необходим для синтеза этой функциональности.

Если я правильно помню, для свойств только для чтения аналогичное предположение также выполняется.

person Eiko    schedule 16.10.2012
comment
В моем случае мне нужно резервное хранилище, так как мне нужно выполнить некоторую инициализацию в геттере и обновление пользовательского интерфейса в сеттере. Я так понимаю, линейка @synthesize — это то, что нужно? Жаль, мне понравилось, какой чистый файл без них :) - person Kevin Renskers; 16.10.2012
comment
Да, в этом случае они нужны - или вы можете поместить ивар в свой список объявлений, даже в свой .m файл. - person Eiko; 16.10.2012

В самой последней версии компилятора/среды выполнения, когда вы используете

@synthesize testArray = _testArray;

компилятор создает

  • _testArray ivar, если еще не существует;
  • метод testArray, если вы его не реализовали;
  • метод setTestArray:, если вы его не реализовали.

Если вы используете

@synthesize testArray;

компилятор создает testArray ivar, если он еще не существует, вместо _testArray.

Если вы не используете @synthesize и полагаетесь на автосинтез, ивар _testArray создается только в том случае, если (оба должны применяться)

  • _testArray еще не существует;
  • хотя бы один метод был синтезирован (геттер для readonly, геттер и/или сеттер для readwrite).

В вашем примере вы реализовали все методы, поэтому автосинтез ничего не синтезирует, поэтому он не создает ивар. Вы можете либо объявить _testArray ivar самостоятельно, либо использовать явный синтез, как вы это сделали.

person Guillaume    schedule 16.10.2012
comment
Спасибо за ваш подробный ответ. - person Kevin Renskers; 16.10.2012
comment
Во второй части вашего ответа я не уверен, что вам требуется геттер/сеттер, прежде чем он сгенерирует iVar. У меня есть много @property, у которых нет явного геттера/сеттера без явного @synthesize, и я могу получить к ним доступ через [self myProperty] или _myProperty. Современная среда выполнения исключает этот шаблонный код. - person Tim Reddy; 16.10.2012
comment
Вот что я говорю. Если у вас есть @property без явного @synthesize и без реализации геттера/сеттера, то геттер/сеттер будет автоматически синтезирован, поэтому будет создан _propertyname ивар. - person Guillaume; 16.10.2012
comment
У меня есть вопрос, не был ли в вашем примере уже объявлен testArray, указав (at) свойство *testArray? Это одна из вещей, которая меня озадачивает, в моем случае мне определенно не нужен (at) синтез, потому что я создал свой собственный метод установки и получения и уже объявил (at) свойство, если у меня нет (at) синтеза Я получаю сообщение об ошибке. Это, безусловно, лучший ответ, который я читал, (в) Синтез и (в) Свойство очень абстрактны. - person jigzat; 25.02.2014

Я провел несколько тестов:

Согласно недавнему соглашению Objective-c, вам не нужно синтезировать свойства.

Если вы сделаете

@property (strong, nonatomic) Business* theBiz;

iOS автоматически создаст частную переменную ivar с именем _theBiz;

Если вы реализуете только геттер или сеттер, он работает нормально:

-(void)setTheBiz:(Business *)theBiz
{
    _theBiz = theBiz;
}

Однако, если вы объявите ОБА, даже если одна из них просто пустая функция, вы получите ошибку компиляции.

-(void)setTheBiz:(Business *)theBiz
{
    _theBiz = theBiz;
}

-(Business *) theBiz
{

}

Когда вы реализуете ОБА геттер и сеттер, вы получите ошибку компиляции, в которой говорится, что такой вещи, как _theBiz, не существует.

Это можно легко исправить, добавив:

@synthesize theBiz = _theBiz;

Но это разрушает весь смысл этой удивительной новой функции Objective-c.

Интересно, это так задумано или я просто что-то упускаю? Что делает яблоко?

Мое лучшее предположение, что это ошибка.

Ответ Гийома не касается этого факта.

Он сказал, что

по крайней мере был синтезирован один метод

Похоже, что _theBiz был бы создан, если бы был установлен только ОДИН геттер или сеттер. Когда установлены оба, он больше не создается, и это должно быть ошибкой. На самом деле вообще ничего не нужно устанавливать, и ивар все равно будет создан.

Единственный способ исправить это - явно сделать

@synthesize theBiz = _theBiz;
person Anonymous White    schedule 19.10.2012
comment
Ответ Гийома действительно касается этого факта: в вашем примере вы реализовали все методы, поэтому автосинтез ничего не синтезирует, поэтому он не создает ивар. Вы можете либо объявить переменную _testArray самостоятельно, либо использовать явный синтез, как вы это сделали. Кроме того, ваш ответ в основном совпадает с моим вопросом :) - person Kevin Renskers; 19.10.2012
comment
Гийом сказал так: синтезирован как минимум один метод (геттер для чтения, геттер и/или сеттер для чтения). Это неверно. Если ОБА метода были синтезированы, ивар НЕ создается. Также нет причин не создавать ivar, если у вас реализованы оба метода. - person Anonymous White; 20.10.2012
comment
Я должен просто удалить этот ответ, если он вам не нравится. Я все еще думаю, что это ошибка. - person Anonymous White; 20.10.2012