保留和释放 nsstring

Retain and release nsstring

str 是我拥有的 NSString。释放它是我的责任, 因为我打电话给 initWithString:

if (![[str substringFromIndex:str.length-1] isEqualToString:@"\n"])
{
    str = [str stringByAppendingString:@"\n"];
}

如果到达 if 语句中的行,我将失去 str var.

的所有权

所以当我稍后发布 str 时,我的应用程序因僵尸实例而崩溃:

[str release];

如果 if 语句为 NO(false),一切正常。

如何维护 str 的所有权?

注意 str 可能很长我不想初始化另一个 NSString

您需要进行正常的内存管理:

if (![[str substringFromIndex:str.length-1] isEqualToString:@"\n"])
{
    NSString *newStr = [str stringByAppendingString:@"\n"];
    [str release];
    str = [newStr retain];
}

请记住,stringByAppendingString: returns 是一个自动释放的字符串(它还会创建一个全新的字符串)。

建议一:使用ARC。它为您解决了这些问题。这是迄今为止最好的解决方案。

正如 rmaddy 所说,Xcode 有一个将应用程序转换为 ARC 的自动化工具。查看编辑菜单,在重构 > 转换为 Objective-C ARC 下。这个过程相当轻松。它标记了它自己无法弄清楚的事情(通常只有几件事。)在你清理了这些问题之后你就离开了 运行 并且再也不用担心保留计数。

建议 1a:按照@rmaddy 的建议,将 str 设为可变字符串。

那么您的代码将如下所示:

[str appendString: @"\n"];

它更简单、更易于阅读、内存效率更高,并且在 ARC 和手动引用计数中的工作方式完全相同。

否则,将 str 更改为保留 属性

@property (nonatomic, retain) NSString *str);

然后使用属性表示法:

if (![[self.str substringFromIndex: self.str.length-1] isEqualToString:@"\n"])
{
    self.str = [self.str stringByAppendingString:@"\n"];
}

当您执行此操作时,属性 的 setter 负责在将新值分配给 属性 之前释放 str 属性 中的旧对象。

但是请注意,将对象分配给保留 属性 会增加它的保留计数。这会造成泄漏:

self.str = [NSString alloc] initWithFormat: @"number %d", value];

(因为所有 alloc/init 调用 return 保留计数为 1 的对象)

然后 属性 再次保留它。

那段代码应该这样写:

self.str = [[NSString alloc] initWithFormat: @"number %d", value] autorelease];