保留和释放 nsstring

Posted

技术标签:

【中文标题】保留和释放 nsstring【英文标题】:Retain and release nsstring 【发布时间】:2015-03-05 19:29:41 【问题描述】:

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

【问题讨论】:

仅供参考 - 调用 stringByAppendingString: 会执行 init 一个全新的字符串。 真的吗? :) 但也许旧字符串会在 :) 之前被释放? @rmaddy 你有什么建议? 请问您为什么不使用ARC?现在是 2015 年。除非你真的不得不这样做,否则不要让你的生活变得更艰难。 “你有什么建议?” 使用 ARC。 Xcode 使转换变得容易。 【参考方案1】:

你需要做正常的内存管理:

if (![[str substringFromIndex:str.length-1] isEqualToString:@"\n"])

    NSString *newStr = [str stringByAppendingString:@"\n"];
    [str release];
    str = [newStr retain];

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

【讨论】:

无论如何都不能在不创建新 srt 的情况下向 str 添加新行 只有一种方法——使用NSMutableString【参考方案2】:

建议 1:使用 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"];

当您这样做时,属性的设置器会在为属性分配新值之前释放 str 属性中的旧对象。

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

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

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

然后该属性再次保留它。

那段代码应该这样写:

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

【讨论】:

以上是关于保留和释放 nsstring的主要内容,如果未能解决你的问题,请参考以下文章

保留和释放 nsstring

有人能告诉我在objective-c中保留和释放到底做了啥吗?

基本保留、自动释放问题

如何在 iPhone / iPad 的应用程序中正确使用保留和释放

我是不是必须“释放”我声明为具有属性属性“保留”和“非原子”的 IBOutlets 的 UI 对象?

从自动释放对象上的保留转向引用是不是需要释放?