помилка: атомна властивість, що записується, не може з'єднати синтезований сеттер / getter з визначеним користувачем сеттером / геттером


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
{
    //..
}

Я бачу, чому помилка створюється. Я кажу компілятору синтезувати мої доступності властивостей (як getter, так і setter), а потім негайно після цього я переосмислюю програму вручну. Цей код завжди трохи пахнув.

Отже, який правильний спосіб зробити це? Якщо я використовую @dynamicзамість @synthesize, мені доведеться також писати геттер. Це єдиний спосіб?


Це трапляється лише з atomicвластивостями? У випадку атомних властивостей може бути хорошою ідеєю синхронізувати пару getter / setter щодо стратегії блокування. Це складно, якщо одна частина синтезується, а інша - спеціальний код.
Микола Рухе

Це, безумовно, проходить, якщо я роблю майно неатомічним. Цікаво. Я навіть не думав про проблему синхронізації.
e.James

Я відвідав цю тему, щоб знайти вирішення саме цієї проблеми. Я не дуже хочу писати геттер і сеттер самостійно. Ну добре…
Константіно Царухас

За замовчуванням кожна властивість є атомною, і нам потрібно зробити їх неатомічними. Атомні властивості безпечні для потоків, тому ми не можемо реалізувати для них сеттер і геттер, оскільки це змінить функціональну безпеку для потоків. Я сподіваюся, що ви отримаєте причину, чому ви отримуєте цю помилку
Мохд Хайдер

Відповіді:


218

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

Компілятор попереджає вас про @propertyте, що ви оголосили атомним (тобто, опустивши nonatomicключове слово), проте ви надаєте неповну реалізацію способів синхронізації доступу до цього ресурсу.

Щоб це попередження зникло:

Якщо ви оголосите @propertyатомним, виконайте одну з наступних дій:

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

Якщо оголосити @propertyз , (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;
}

12

Це питання, серед інших найпопулярніших звернень, які ви отримуєте від пошуку "об’єктивної властивості об'єктивного C", не оновлюється інформацією про "setter =" або "getter =".

Отже, щоб надати більше інформації з цього питання:

Ви можете надіслати @property викликом власним методом, написавши

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

Зверніть увагу на товсту кишку для поставленого методу сеттера.

Довідкова документація Apple

EDIT: Я не зовсім впевнений, як нові зміни властивостей Objective-C (тепер вони набагато розумніші) змінюють відповіді на це питання. Можливо, все це слід позначити як застаріле.


Я виявив, що встановлення методу встановлення насправді не видалило попередження. наприклад -> "@property (призначити, setter = setDelegate :) делегат id;" У цьому випадку все, що я можу зробити, - це додати власний getter або додати неатомічну властивість, що я не впевнений, чи слід, враховуючи, що я встановлюю делегата "атомно", не має значення неатомічне властивість або я так розумію.
Девід ван Дагтерен

Цікаво, Девіде. У якій версії «Objective-C» це (я вважаю, що XCode-версія буде кориснішою)? Я не впевнений, що на це впливають останні зміни в Objective-C, зокрема з iOS 6.
Matias Forbord

0

Для інших, хто отримує цю помилку не з причини, описаної в ОП, ви, ймовірно, маєте те саме питання, що і я:

У вас є властивість @ з тим самим іменем, що і метод - ().

Щось на зразок цього:

@property UIView *mainView;

-(UIView *)mainView;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.