エラー:書き込み可能なアトミックプロパティは、合成されたセッター/ゲッターをユーザー定義のセッター/ゲッターとペアにすることはできません


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、ゲッターも作成する必要があります。それが唯一の方法ですか?


これはatomicプロパティでのみ発生しますか?アトミックプロパティの場合は、ロック戦略に関してゲッター/セッターのペアを同期させることをお勧めします。一方が合成され、他方がカスタムコードである場合、これは困難です。
Nikolai Ruhe 2010

プロパティを非アトミックにすると、確実になくなります。面白い。私は同期の問題についてさえ考えていませんでした。
e.James、2010

このトピックにアクセスして、その正確な問題の解決策を見つけました。自分でゲッターとセッターを書いたくありません。まあ…
コンスタンティーノ・ツァロウは

デフォルトでは、すべてのプロパティはアトミックであり、明示的に非アトミックにする必要があります。アトミックプロパティはスレッドセーフであるため、スレッドセーフ機能が変更されるため、セッターおよびゲッターを実装できません。このエラーが発生する理由を教えてください。
Mohd Haider 2015年

回答:


218

私は同じ問題を抱えていたので、少し調査した後、この問題についての私の結論は次のとおりです。

コンパイラー@propertyは、アトミックとして宣言した(つまり、nonatomicキーワードを省略して)ことを警告しますが、そのプロパティへのアクセスを同期する方法の実装が不完全です。

その警告を消すには:

a @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;
}

12

この質問は、「目的のCカスタムプロパティ」を検索して得られる他の上位ヒットの中でも、「setter = "または" getter = "に関する情報で更新されていません。

したがって、この質問に関する詳細情報を提供するには:

@property呼び出しに独自のメソッドを指定するには、次のように記述します。

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

提供されているセッターメソッドのコロンに注意してください。

Appleのドキュメントを参照

編集:Objective-Cのプロパティへの新しい変更(現在ははるかにインテリジェントになっています)がこの質問への回答をどのように変更するかは、よくわかりません。おそらく、すべてが古くなっているとマークする必要があります。


setterメソッドを設定しても実際には警告が削除されないことがわかりました。例-> "@property(assign、setter = setDelegate :) id delegate;" この場合、私ができることは、自分のゲッターを追加するか、非原子的なプロパティを追加することだけです。デリゲートを「原子的に」設定しているので、非原子的なプロパティを持つことは問題ではありません。 、または私は理解しています。
David van Dugteren、2012

面白い、デビッド。これはObjective-Cのどの「バージョン」ですか(XCodeのバージョンがより役立つと思います)。特にiOS 6でのObjective-Cに対する最近の変更がこれにどのような影響を与えるかはわかりません。
Matias Forbord 2012

0

OPで説明されている理由ではなく、このエラーが発生している他の人にとって、私と同じ問題が発生している可能性があります。

-()メソッドと同じ名前の@プロパティがあります。

このようなもの:

@property UIView *mainView;

-(UIView *)mainView;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.