题 在Objective-C中正确覆盖setter


我只是试图覆盖属性的标准合成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?
}

18
2017-09-11 12:31


起源


从使用情况来看 retain 我知道你没有使用ARC? - waldrumpus
是的我没有使用弧线 - E. Lüders
你只需要自己设置保留计数 - 就是这样 - MrBr


答案:


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

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

或者,你可以这样做

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

28
2017-09-11 12:46



+1表示正常! - Damo


在学习Hot Licks的接受答案后编辑

x的财产申报和综合

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

过度使用的二传手

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

5
2017-09-11 12:39



谢谢,就是我想要的! - E. Lüders
但想象一下如果你这样做 self.x = [self.x objectAtIndex:0];。 - Hot Licks
self.x = [self.x objectAtIndex:0];只是弄乱了我的脑袋:-) - Damo
问题(对于那些还没有得到它的人来说,问题的结果来自于 objectAtIndex 仅由当前对象(可能是NSArray)保留 x。如果 setX 释放当前对象,然后仅保留新值NSArray 以及其中的所有对象 将被释放,意味着即将被设定的价值 x 将会被释放。这可能会导致一些相当模糊和令人沮丧的错误。 - Hot Licks


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

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

吸气剂同样适用。


5
2017-09-11 12:38



我知道,但谢谢。不,我不想给他们另一个名字。我想将自定义代码添加到setter。 - E. Lüders


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

你需要的 if 声明,因为否则,如果有什么和_something 已经 同样,你过度释放物体,它可能会消失,并有问题。


4
2017-09-11 12:39



呃,但NSInteger不是一个对象。 - Hot Licks
D'哦!复制了错误的例子。将编辑。 - Amy Worrall
仍然失败了 self.something = [self.something objectAtIndex:0]; - Hot Licks