在目标C中在二传手中保留和释放

时间:2012-10-11 19:26:37

标签: objective-c ios memory-management

初学者问题:

我正在尝试了解一些基本的内存管理。如果我重写了一个setter方法,下面是否能充分处理传入字符串的内存管理?

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

我的逻辑是,一旦我们进入if语句,我想获取传入字符串的所有权,因此保留。接下来我发布_myString对象。然后我将_myString对象设置为字符串对象。这是我困惑的根源:我是否需要保留myString对象?或者我是否因为将其设置为字符串对象而对其拥有所有权?

谢谢!

3 个答案:

答案 0 :(得分:4)

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

当您在字符串上调用retain时,您将该实例的引用计数递增1。将字符串的值指定为_myString不会更改实际实例(现在string_myString指向),因此不需要第二次保留,并且不正确。< / p>

所有这一切,你所得到的都是多余的。 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;
}

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

答案 1 :(得分:1)

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

它适用于iOS 4,而且由于目前的iOS版本为6,所以现在使用ARC比使用ARC新版本时更好。

答案 2 :(得分:0)

还有一点缩短形式:

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

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

  

永远不要只保留字符串。这可以避免调用者在您不知情的情况下将其更改为您。不要假设因为你接受的NSString实际上并不是NSMutableString。