web-dev-qa-db-ja.com

@propertyセッターと無限ループをオーバーライドする

クラスAがあります。

@interface ClassA : NSObject {
}
@property (nonatomic, assign) id prop1;
@end

@implementation
@synthesize prop1;
@end

それから私はサブクラスを持っています

@interface ClassB : ClassA {
}
@end

@implementation

- (id)init {
    self = [super init];
    if (self) {
    }
    return self;
}

//This is infinite loop
- (void) setProp1:(id)aProp
{
    self.prop1 = aProp;
}
@end

classBのsetProp1がClassB内から[ClassB setProp1:val]を呼び出すため、これは無限ループです。

私はすでに[super setProp1]を呼び出してみましたが、これは

@propertyを上書きし、上書きされたセッター内に値を割り当てる方法は?そして、ClassAを変更できないとしましょう。

38
Marcin

ドット構文を使用してセッターを呼び出すことなく、インスタンス変数に直接割り当てるだけです。

- (void) setProp1:(id)aProp
{
    self->prop1 = aProp;
}

しかし、そのようなことは疑問を投げかけます。このアクセサーが行うことは、まさに親が行ったこととまったく同じです。つまり、親をオーバーライドする意味は何でしょうか。

58
Sherm Pendley

XCode 4.5+およびLLVM 4.1では、@ synthesizeを実行する必要はありません。参照する_prop1を取得します。

- (void) setProp1:(id)aProp
{
    _prop1 = aProp;
}

うまくいきます。

23
bollhav

再帰呼び出しが作成されるため、セッター内で「self」を使用しないでください。

また、同じオブジェクトを割り当てていないことを確認し、新しいオブジェクトを保持して、割り当て前に古いオブジェクトを解放する必要があります。

また、上記のように、セッター名を再定義する必要があります。

@synthesize prop1 = prop1_; 

...

- (void) setProp1:(id)aProp
{
    if (prop1_ != aProp) {
        [aProp retain]; 
        [prop1_ release]; 
        prop1_ = aProp;
    }
}
9
Chris Livdahl

別の方法は、合成された変数を次のように別の名前に設定することです:

@synthesize selectedQuestion = _selectedQuestion;

そして、それを_selectedQuestionとして参照します。これにより、self.selectedQuestionを意図したときに誤ってselectedQuestionを書き込むことを防ぎます。

ただし、Appleアンダースコアの使用はお勧めしません。別の名前を使用することもできますが、@ Shermの方法が最良です。imhoです。

5
pixelfreak

単に@synthesizeサブクラスで目的のプロパティを指定すると、そのプロパティを名前として使用して、プロパティに直接アクセスできます。

メインクラスインターフェイス:

@interface AClass : NSObject

@property (nonatomic, assign) id<someProtocol> delegate;

@end

サブクラスインターフェイス:

@interface BCLass : AClass
@end

サブクラスの実装:

@implementation BCLass

@synthesize delegate = _delegate;

- (void)setDelegate:(id<someProtocol>)d{
    _delegate = d;
}

@end
4
Daniel