【问题标题】:Correctly override setter in Objective-C在 Objective-C 中正确覆盖 setter
【发布时间】:2016-10-19 11:58:24
【问题描述】:

我只是试图覆盖一个属性的标准合成设置器。到目前为止一切都很好,我只是将 ivar 设置为我的新值。但是后来我问自己'保留属性的保留计数会发生什么'......我没有找到可以向我解释这一点的好答案。所以我在这里问。如果我覆盖设置为retain 的属性设置器,我需要注意什么,我该如何正确地做到这一点?我不使用 ARC。

这是一个例子:

@property(nonatomic)NSInteger number;

- (void)setNumber:(NSInteger)number {
    _number = number;  // This should be fine, since it's no retained object I want to set
}


@property(nonatomic, retain)NSObject *something;

- (void)setSomething:(NSObject *)something {
    _something = something;  // This is not fine. As far as I know you should never do sth. like this... But how do I set it correctly?
}

【问题讨论】:

  • retain的用法我猜你没有使用ARC?
  • 您只需要自己设置保留计数 - 仅此而已

标签: iphone objective-c ios


【解决方案1】:
-(void) setAnObject:(NSObject*) someObject {
    if (_anObject != someObject) {
       NSObject* savedObject = _anObject;
       _anObject = [someObject retain];
       [savedObject release];
    }
}

如果您在保留新指针之前释放旧指针,您可能会遇到这样一种情况:您从旧对象中的值设置值,而旧对象的释放导致新对象POOF!就在它被保留之前。

或者,你可以这样做

....
[someObject retain];
[_anObject release];
_anObject = someObject;
...

【讨论】:

    【解决方案2】:

    在研究 Hot Licks 接受的答案后编辑

    x的属性声明与综合

    @property (nonatomic, retain) ClassX x;
    @synthesize x = _x;
    

    x 的重写设置器

    - (void)setX:(ClassX *)x;
    {
      if (x != _x)
      {
        [x retain];
        [_x release];
        _x = x;
        // custom code here
      }
    }
    

    【讨论】:

    • 谢谢,正是我想要的!
    • 但是想象一下,如果你这样做self.x = [self.x objectAtIndex:0];
    • self.x = [self.x objectAtIndex:0];只是在弄乱我的头:-)
    • 问题(对于那些还没有得到它的人来说,是objectAtIndex 的结果仅被x 中的当前对象(可能是NSArray)保留。如果@987654326 @释放当前对象,然后才保留新值,NSArray和其中的所有对象都会被释放,这意味着将要设置到x中的值将被释放。这可以导致一些相当模糊和令人沮丧的错误。
    【解决方案3】:

    您是否只是为了使用不同的名称而覆盖 setter?如果是这种情况,您可以通过更改属性定义来做到这一点:

    @property(nonatomic, setter = nameOfSetter: )NSInteger number;
    

    getter 也一样。

    【讨论】:

    • 我知道,但是谢谢。不,我不想给他们取另一个名字。我想在 setter 中添加自定义代码。
    【解决方案4】:
    - (void) setSomething:(NSObject*) something
    {
        if (something != _something)
        {
            [_something release];
            _something = [something retain];
        }
    }
    

    您需要if 语句,否则,如果某物和_某物已经相同,您将过度释放该对象,使其可能消失,并出现问题。

    【讨论】:

    • 呃,但是 NSInteger 不是对象。
    • self.something = [self.something objectAtIndex:0]; 仍然失败
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    相关资源
    最近更新 更多