【问题标题】:Override @property setter and infinite loop覆盖@property setter 和无限循环
【发布时间】:2011-06-19 22:10:34
【问题描述】:

有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。

【问题讨论】:

  • “我已经尝试调用 [super setProp1] 但是这个”...?出了什么问题? super 在这里是正确的。
  • super 仅在 super 中更改值。 self.prop1 为 null 并且 super.prop1 有值。 self->prop1 解决问题(正如 Sherm 建议的那样)
  • self.prop1 和 super.prop1 绝对应该返回不同的值。你是否也覆盖了 getter 方法?
  • 是的,我这样做了,它从这个设置器返回“aProp”。
  • getter 的超类实现不应该已经这样做了吗?

标签: objective-c ios overriding subclass


【解决方案1】:

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

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

可以正常工作。

【讨论】:

    【解决方案2】:

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

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

    不过,这样的问题就引出了问题。所有这个访问器所做的正是父级所做的——那么重写父级的意义何在?

    【讨论】:

    • example 仅用于示例目的。
    • 除非使用 GCC 4.2,否则不需要 self-> 部分。
    • 是的,但 AFAIK 并没有什么害处,它可以作为视觉提醒,我正在做一些不寻常的事情,访问 ivar 而不通过其访问器方法。
    • 这对我不起作用,请查看我的解决方案:stackoverflow.com/a/12465444/662605
    • @Daniel 你拥有他所拥有的一切。
    【解决方案3】:

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

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

    你应该重新定义setter名字,就像上面建议的那样:

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

    【讨论】:

    • 您应该只对retain 属性执行此操作,OP 的示例是assign 属性。
    • 拯救我的部分是你不应该在setter中使用“self”,因为这会创建递归调用。一旦我替换了self。 用下划线表示魔法发生了。
    【解决方案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
    

    【讨论】:

      【解决方案5】:

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

      @synthesize selectedQuestion = _selectedQuestion;
      

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

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

      【讨论】:

        猜你喜欢
        • 2020-02-27
        • 2012-07-12
        • 1970-01-01
        • 2017-01-03
        • 2014-09-02
        • 2020-03-04
        • 2013-09-27
        • 2018-11-08
        • 2013-01-19
        相关资源
        最近更新 更多