2011-06-19 46 views
35

有一类与:覆盖@property setter和无限循环

@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 

,这是无限循环,因为从setProp1 ClassB的调用[ClassB的setProp1:VAL]从ClassB内部。

我已经尝试过电话[超级setProp1]但这

如何覆盖@property和分配覆盖二传手内在价值?假设我无法修改ClassA。

+0

“我已经尝试致电[super setProp1],但是这个”...?有什么问题? 'super'在这里是正确的。 –

+0

仅超级超级更改值。 self.prop1为null,super.prop1有价值。自我> prop1做的伎俩(如舍姆建议) – Marcin

+1

self.prop1和super.prop1应该肯定*不*返回不同的值。你是否也重写了getter方法? –

回答

54

刚分配到直接的实例变量,而无需使用点语法来调用setter方法:

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

那样的,虽然回避了一个问题。所有这些访问者所做的都是父母所做的 - 那么覆盖父母有什么意义呢?

+3

示例仅用于示例目的。 – Marcin

+2

除非使用GCC 4.2,否则不需要使用'self->'部分。 – bbum

+3

确实如此,但是AFAIK并没有什么坏处,它可以作为一种视觉提醒,我正在做一些与众不同的事情,在不通过访问方法的情况下访问伊娃。 –

5

另一种方法是将合成的变量设置为另一名称,像这样:

@synthesize selectedQuestion = _selectedQuestion; 

然后将其称为_selectedQuestion。这可以防止在您表示self.selectedQuestion时意外写入selectedQuestion。

但是,Apple建议不要使用下划线。你可以使用另一个名字,但@ Sherm的方法是最好的,恕我直言。

9

您不应该在setter中使用“self”,因为这会创建递归调用。

此外,您应该检查以确保您不分配相同的对象,保留新对象并在分配前释放旧对象。

你应该重新定义制定者的名字,上面的建议:

@synthesize prop1 = prop1_; 

... 

- (void) setProp1:(id)aProp 
{ 
    if (prop1_ != aProp) { 
     [aProp retain]; 
     [prop1_ release]; 
     prop1_ = aProp; 
    } 
} 
+0

你应该只为'retain'属性做这个,OP的例子是'assign'属性。 – pancake

+0

救了我的部分是**你不应该在setter中使用“self”,因为这会创建递归调用。**一旦我用下划线替换了** self **,魔法就发生了。 – LargeGlasses

4

只需@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 
21

在Xcode 4.5+和LLVM 4.1没有必要@synthesize,你会得到一个_prop1来指代。

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

将工作得很好。