ошибка: записываемое атомарное свойство не может соединить синтезированный сеттер / получатель с определенным пользователем сеттером / получателем

128

Недавно я попытался скомпилировать более старый проект 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
{
    //..
}

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

Итак, как правильно это сделать? Если я использую @dynamicвместо @synthesize, мне также придется написать геттер. Это единственный способ?

e.James
источник
Это происходит только со atomicсвойствами? В случае атомарных свойств было бы неплохо поддерживать синхронизацию пары геттер / сеттер в отношении стратегии блокировки. Это сложно, если одна часть синтезируется, а другая представляет собой собственный код.
Николай Рухе
Это определенно исчезнет, ​​если я сделаю свойство неатомарным. Интересный. Я даже не думал о синхронизации.
e.James
Я посетил эту тему, чтобы найти решение именно этой проблемы. Я действительно не хочу писать геттер и сеттер сам. Ну что
ж
По умолчанию каждое свойство является атомарным, и нам нужно явно сделать его неатомарным. Атомарные свойства являются потокобезопасными, поэтому мы не можем реализовать для них сеттер и получатель, потому что это изменит его поточно-безопасную функциональность. Надеюсь, вы понимаете причину появления этой ошибки.
Mohd Haider

Ответы:

218

У меня была такая же проблема, и после небольшого исследования я пришел к выводу об этой проблеме:

Компилятор предупреждает вас об объекте, @propertyкоторый вы объявили как атомарный (т. Е. Опуская nonatomicключевое слово), но при этом предоставляете неполную реализацию того, как синхронизировать доступ к этому свойству.

Чтобы это предупреждение исчезло:

Если вы объявляете @propertyатомарный объект, выполните одно из следующих действий:

  • используйте @dynamicили;
  • использовать @synthesizeи хранить синтезированные сеттер и геттер или;
  • предоставить ручную реализацию как установщика, так и получателя (без использования одной из вышеуказанных директив).

Если вы объявляете @propertywith, (nonatomic)вы можете смешивать ручные и синтезированные реализации геттеров и сеттеров.

Обновление: примечание об автосинтезе свойств

Начиная с LLVM 4.0, CLang обеспечивает автосинтез объявленных свойств, которых нет @dynamic. По умолчанию, даже если вы не укажете @synthesize, компилятор предоставит вам методы получения и установки. Однако правило для атомарных свойств остается тем же: либо пусть компилятор предоставит и геттер, и сеттер, либо реализовать их оба самостоятельно!

Окти
источник
Спасибо! «объявить @property с помощью (неатомного)»
Nianliang
14

Вам также необходимо реализовать геттер. Пример:

// 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;
}
arturgrigor
источник
12

Этот вопрос, среди других популярных запросов, которые вы получаете при поиске по запросу "объектное свойство C", не обновляется информацией о "setter =" или "getter =".

Итак, чтобы предоставить дополнительную информацию по этому вопросу:

Вы можете предоставить вызов @property своим собственным методом, написав

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Обратите внимание на двоеточие для предоставленного метода установки.

Справочная документация Apple

РЕДАКТИРОВАТЬ: Я не совсем уверен, как новые изменения свойств Objective-C (теперь они намного умнее) меняют ответы на этот вопрос. Возможно, все это стоит пометить как устаревшее.

Матиас Форборд
источник
Я обнаружил, что установка метода установки на самом деле не удаляет предупреждение. например -> "@property (assign, setter = setDelegate :) делегат идентификатора;" В этом случае все, что я могу сделать, это добавить свой собственный геттер или добавить неатомное свойство, в чем я не уверен, должен ли я, учитывая, что я сам устанавливаю делегат `` атомарно '', не имеет значения наличие неатомного свойства По крайней мере, я так понимаю.
Дэвид ван Дугтерен
Интересно, Дэвид. В какой «версии» Objective-C это (я полагаю, что версия XCode была бы более полезной)? Я не уверен, что на это повлияли недавние изменения в Objective-C, особенно в iOS 6.
Матиас Форборд
0

Для других, кто получает эту ошибку не по причине, описанной OP, у вас, вероятно, такая же проблема, как и у меня:

У вас есть @property с тем же именем, что и у метода - ().

Что-то вроде этого:

@property UIView *mainView;

-(UIView *)mainView;
Альберт Реншоу
источник