正确覆盖Objective-C中的setter

时间:2012-09-11 12:31:37

标签: iphone objective-c ios

我只是试图覆盖属性的标准合成setter。到目前为止一切都很好我只是将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?
}

4 个答案:

答案 0 :(得分:28)

-(void) setAnObject:(NSObject*) someObject {
    if (_anObject != someObject) {
       NSObject* savedObject = _anObject;
       _anObject = [someObject retain];
       [savedObject release];
    }
}

如果在保留新指针之前释放旧指针,则可能出现从旧对象中的值设置值的情况,旧对象的释放导致新对象进入POOF!就在它被保留之前。

或者,您可以

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

答案 1 :(得分:5)

你是否因为有不同的名字而覆盖了这些人?如果是这种情况,您可以通过更改属性定义来执行此操作:

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

相同的吸气剂。

答案 2 :(得分:5)

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

属性声明和x的合成

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

x的过度使用的setter

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

答案 3 :(得分:4)

- (void) setSomething:(NSObject*) something
{
    if (something != _something)
    {
        [_something release];
        _something = [something retain];
    }
}

你需要if语句,否则,如果某些东西和_something 已经相同,你就会过度释放该对象,让它消失,并且有问题。