私は最近(以前はうまくコンパイルされていた)古い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
を使用する場合、ゲッターも作成する必要があります。それが唯一の方法ですか?
私は同じ問題を抱えていたので、少し調査した後、この問題に関する私の結論を以下に示します。
コンパイラーは、アトミックとして宣言した@property
(つまり、nonatomic
キーワードを省略すること)について警告しますが、そのプロパティへのアクセスを同期する方法の不完全な実装を提供します。
その警告を消すには:
@property
がアトミックであると宣言する場合、次のいずれかを実行します。
@dynamic
を使用するか、@synthesize
を使用して、合成されたセッターとゲッターを保持するか、@property
を(nonatomic)
で宣言すると、ゲッターとセッターの手動実装と合成実装を混在させることができます。
更新:プロパティの自動合成に関する注意
LLVM 4.0以降、CLangは@dynamic
ではない宣言されたプロパティの自動合成を提供します。デフォルトでは、@synthesize
を省略した場合でも、コンパイラはgetterおよびsetterメソッドを提供します。ただし、アトミックプロパティのルールは同じままです。ゲッターとセッター、ORの両方をコンパイラーにboth提供させるそれら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ドキュメント
編集:Objective-Cのプロパティに対する新しい変更(現在ははるかにインテリジェントになっている)がこの質問に対する回答をどのように変更するかはよくわかりません。おそらく、すべて古いとマークする必要があります。
OPが説明されている理由ではなく、このエラーを受け取っている他の人には、おそらく私と同じ問題があります:
-()メソッドと同じ名前の@プロパティがあります。
このようなもの:
@property UIView *mainView;
-(UIView *)mainView;