web-dev-qa-db-ja.com

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

私は最近(以前はうまくコンパイルされていた)古い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を使用する場合、ゲッターも作成する必要があります。それが唯一の方法ですか?

127
e.James

私は同じ問題を抱えていたので、少し調査した後、この問題に関する私の結論を以下に示します。

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

その警告を消すには:

@propertyがアトミックであると宣言する場合、次のいずれかを実行します。

  • @dynamicを使用するか、
  • @synthesizeを使用して、合成されたセッターとゲッターを保持するか、
  • セッターとゲッターのbothの手動実装を提供します(上記のディレクティブのいずれも使用しません)。

@property(nonatomic)で宣言すると、ゲッターとセッターの手動実装と合成実装を混在させることができます。

更新:プロパティの自動合成に関する注意

LLVM 4.0以降、CLangは@dynamicではない宣言されたプロパティの自動合成を提供します。デフォルトでは、@synthesizeを省略した場合でも、コンパイラはgetterおよびsetterメソッドを提供します。ただし、アトミックプロパティのルールは同じままです。ゲッターとセッター、ORの両方をコンパイラーにboth提供させるそれらbothご自身!

217
octy

ゲッターも実装する必要があります。例:

// 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;
}
13
arturgrigor

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

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

次のように記述することにより、独自のメソッドで@property呼び出しを提供できます。

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

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

参照 Appleドキュメント

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

12
Matias Forbord

OPが説明されている理由ではなく、このエラーを受け取っている他の人には、おそらく私と同じ問題があります:

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

このようなもの:

@property UIView *mainView;

-(UIView *)mainView;
0
Albert Renshaw