覆盖@property setter和无限循环

时间:2011-06-19 22:10:34

标签: objective-c ios override subclass

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并在覆盖的setter中分配值?我们假设我无法修改ClassA。

5 个答案:

答案 0 :(得分:56)

直接分配给实例变量,而不使用点语法来调用setter:

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

但是这种问题引起了人们的质疑。所有这些访问器确实是父母所做的 - 那么什么是覆盖父母的重点呢?

答案 1 :(得分:22)

使用XCode 4.5+和LLVM 4.1不需要@synthesize,您将获得一个_prop1来引用。

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

工作得很好。

答案 2 :(得分:9)

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

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

您应该重新定义设置者名称,如上所述:

@synthesize prop1 = prop1_; 

...

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

答案 3 :(得分:5)

另一种方法是将合成变量设置为另一个名称,如下所示:

@synthesize selectedQuestion = _selectedQuestion;

然后将其称为_selectedQuestion。当你的意思是self.selectedQuestion时,这可以防止意外写入selectedQuestion。

但是,Apple建议不要使用下划线。您可以使用其他名称,但@ Sherm的方法是最好的,imho。

答案 4 :(得分: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