【问题标题】:Retain and release nsstring保留和释放 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 使转换变得容易。

标签: objective-c release retain


【解决方案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];

【讨论】:

    猜你喜欢
    • 2011-04-13
    • 2011-01-24
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多