Я недавно пытался скомпилировать старый проект XCode (который раньше просто компилировался), и теперь я вижу много ошибок этой формы:
error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter
Шаблон кода, который вызывает эти ошибки, всегда выглядит так:
// Interface:
@property (retain) NSObject * someProperty;
// Implementation:
@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
//..
}
Я понимаю, почему генерируется ошибка. Я говорю компилятору синтезировать мои методы доступа к свойствам (как getter, так и setter), а затем сразу же после этого переопределяю setter вручную. Этот код всегда пах немного.
Итак, как правильно это сделать? Если я использую @dynamic
вместо @synthesize
, мне также придется написать геттер. Это единственный способ?
У меня была та же проблема, и после небольшого исследования, вот мой вывод об этой проблеме:
Компилятор предупреждает вас о @property
, который вы объявили атомарным (то есть, опуская ключевое слово nonatomic
), но вы предоставляете неполную реализацию того, как синхронизировать доступ к этому свойству.
Чтобы это предупреждение исчезло:
Если вы объявляете @property
атомарным, выполните одно из следующих действий:
@dynamic
или;@synthesize
и сохраните синтезированный сеттер и геттер или;Если вы объявляете @property
с (nonatomic)
, то вы можете смешать ручную и синтезированную реализации геттеров и сеттеров.
Обновление: заметка об автосинтезе свойств
Начиная с LLVM 4.0, CLang обеспечивает автоматический синтез для объявленных свойств, которые не являются @dynamic
. По умолчанию, даже если вы пропустите @synthesize
, компилятор предоставит вам методы getter и setter. Тем не менее, правило для атомарных свойств остается тем же: пусть компилятор предоставит both геттер и сеттер, OR реализует их both самостоятельно!
Вы должны также реализовать геттер. Пример:
// Interface:
@property (retain) NSObject * someProperty;
// Implementation:
- (void)setSomeProperty:(NSObject *)newValue
{
@synchronized (self)
{
// ...
}
}
- (NSObject *)someProperty
{
NSObject *ret = nil;
@synchronized (self)
{
ret = [[someProperty retain] autorelease];
}
return ret;
}
Этот вопрос, среди других популярных запросов, полученных при поиске «Пользовательского свойства Objective C», не обновляется информацией о «setter =» или «getter =».
Итак, чтобы предоставить больше информации по этому вопросу:
Вы можете предоставить вызов @property своим собственным методом, написав
@property(setter = MySetterMethod:, getter = MyGetterMethod)
Обратите внимание на двоеточие для предоставленного метода установки.
Справка документация Apple
EDIT: Я не совсем уверен, как новые изменения в свойствах Objective-C (теперь они намного более интеллектуальные) меняют ответы на этот вопрос. Возможно, все это должно быть помечено как устаревшее.
Для тех, кто получает эту ошибку не по описанной причине, вы, вероятно, имеете ту же проблему, что и я:
У вас есть @property с тем же именем, что и у метода - ().
Что-то вроде этого:
@property UIView *mainView;
-(UIView *)mainView;