1

这里的初学者问题:

我试图了解一些基本的内存管理。如果我要重写一个 setter 方法,以下是否足以处理传入字符串的内存管理?

- (void)setMyString:(NSString *)string
{
    if (_myString != string){
        [string retain];
        [_myString release];
        _myString = string;
    }
}

我的逻辑是,一旦我们进入那个 if 语句,我想获得传入字符串的所有权,因此保留。接下来我释放 _myString 对象。然后我将 _myString 对象设置为字符串对象。这是我困惑的根源:此时我是否需要保留 myString 对象?还是由于将其设置为等于字符串对象,我已经拥有它的所有权?

谢谢!

4

3 回答 3

4

你写的都是正确的,除了最后的return _myString陈述

当您在字符串上调用保留时,您将该实例的引用计数加一。将 string 的值赋值为_myString不会改变实际实例(现在由stringand指向_myString),所以第二次保留是不必要的,而且是不正确的。

说了这么多,你所拥有的有点多余。检查的原因if (_myString != string)是,如果你的 setter 是用你已经拥有的同一个对象调用的,你不想在你有机会保留它之前释放那个对象。在这种情况下程序会崩溃,因为你释放它,它被释放,但你保留对它的引用并继续使用它(向它发送消息)。由于对象是相同的,如果函数的参数与实例变量的当前值相同,则只需不执行任何操作即可避免此问题。但是,在释放实例变量之前保留参数是完成完全相同的事情的另一种方法。

因此,您可以执行以下任一操作:

- (void)setMyString:(NSString *)string
{
    if (_myString != string) {
        [_myString release];
        _myString = [string retain];
    }
}

或这个:

- (void)setMyString:(NSString *)string
{
    [string retain];
    [_myString release];
    _myString = string;
}

我倾向于支持第一种方法,因为如果值相同,它会(非常稍微)更快,并且在写出时会更简单一些。但实际上,这取决于个人喜好,您原始问题中的形式也很好。

于 2012-10-11T19:31:32.630 回答
1

不要再使用保留和释放。只需使用ARC,它将为您省去很多麻烦。您不必处理内存泄漏、编写大量保留/释放等。

And it will work with iOS 4, and since the current iOS version is 6, you're good to use ARC now than last year when ARC was new.

于 2012-10-11T20:21:35.593 回答
0

还有一个更短的形式:

- (void)setFoo:(NSString *)aFoo {
  [_foo autorelease];
  _foo = [aFoo copy];
}

此外,来自 google objective-c styleguide 的提示:

永远不要只保留字符串。这样可以避免来电者在您不知情的情况下更改它。不要因为你接受一个 NSString 而假设它实际上不是一个 NSMutableString。

于 2012-10-11T19:58:11.987 回答