ios 覆盖@property setter 和无限循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6405397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:25:36  来源:igfitidea点击:

Override @property setter and infinite loop

objective-ciosoverridingsubclass

提问by Marcin

There is Class A with:

有A类:

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

@implementation
@synthesize prop1;
@end

then I have subclass

然后我有子类

@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

and this is infinite loop because setProp1 from ClassB calls [ClassB setProp1:val] from within ClassB.

这是无限循环,因为来自 ClassB 的 setProp1 从 ClassB 中调用 [ClassB setProp1:val]。

I've already tried call [super setProp1] but this

我已经试过调用 [super setProp1] 但这

How to overwrite @property and assign value inside overwritten setter ? And let's assume I can't modify ClassA.

如何覆盖@property 并在覆盖的 setter 中赋值?让我们假设我不能修改 ClassA。

回答by Sherm Pendley

Just assign to the instance variable directly, without using dot syntax to call the setter:

直接赋值给实例变量,不用点语法来调用setter:

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

That kind of begs the question though. All this accessor does is exactly what the parent would have done - so what's the point of overriding the parent at all?

不过,这种问题引出了问题。所有这些访问器所做的正是父级所做的 - 那么覆盖父级有什么意义呢?

回答by bollhav

With XCode 4.5+ and LLVM 4.1 there is no need to @synthesize, you will get a _prop1 to refer to.

使用 XCode 4.5+ 和 LLVM 4.1 不需要@synthesize,你会得到一个 _prop1 来引用。

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

Will work just fine.

会工作得很好。

回答by Chris Livdahl

You shouldn't use "self" inside the setter since that creates the recursive call.

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

Also, you should check to make sure you're not assigning the same object, retain the new object and release the old object before assignment.

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

And you should redefine the setter name, as suggested above:

您应该重新定义 setter 名称,如上所述:

@synthesize prop1 = prop1_; 

...

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

回答by pixelfreak

Another alternative is to set the synthesized variable to another name like so:

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

@synthesize selectedQuestion = _selectedQuestion;

And then refer to it as _selectedQuestion. This prevents accidentally writing selectedQuestion when you meant self.selectedQuestion.

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

However, Apple recommend against using underscore. You can use another name, but @Sherm's method is the best, imho.

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

回答by Daniel

Simply @synthesizethe desired property in your subclass, then you can use that as the name to access the property directly:

只需@synthesize子类中所需的属性,然后您就可以使用它作为名称直接访问该属性:

Main Class interface:

主类接口:

@interface AClass : NSObject

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

@end

Subclass interface:

子类接口:

@interface BCLass : AClass
@end

Subclass implementation:

子类实现:

@implementation BCLass

@synthesize delegate = _delegate;

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

@end