如何使用ARC将所有权转移出@autoreleasepool

时间:2012-01-17 11:15:19

标签: objective-c ios cocoa automatic-ref-counting autorelease

我有以下代码

- (NSString *)stringByEscapingXMLEntities;
{   
    NSString *result;
    @autoreleasepool {
        result = [self stringByReplacingOccurrencesOfString:@"&" withString:@"&"];
        result = [result stringByReplacingOccurrencesOfString:@"\"" withString:@"""];
        // ... lot of -stringByReplacingOccurrencesOfString: calls
        result = [result stringByReplacingOccurrencesOfString:@" " withString:@" "];
    }
    return result;
}

我现在问自己如何将所有权result转移出方法。在ARC之前,我会在退出autorelease块之前保留result并在方法结束时自动释放它。

谢谢!

4 个答案:

答案 0 :(得分:4)

有两种方法可以做到:

  • 将方法重命名为copyStringByEscapingXMLEntities - copy表示所有权转让,ARC会相应地创建代码。
  • 在标题中将NS_RETURNS_RETAINED附加到方法定义,如下所示:- (NSString *)stringByEscapingXMLEntities NS_RETURNS_RETAINED

编辑:正如'iljawascoding'提到的那样,除了优化之外,@autoreleasepool没有必要保留 -


编辑2:请记住: ARC始终做正确的事。您尝试的所有内容(您的评论)都会生成完全相同的正确程序 - 尽管如果结果定义为__strong,则缺少某些优化。

答案 1 :(得分:2)

完全摆脱自动释放。根据Apple的说法,ARC将在您的代码完成后使用“结果”中存储的临时实例自动插入必要的版本。在这里滚动自己的自动释放池没有任何好处。

答案 2 :(得分:2)

您发布的代码是正确的。任何崩溃都有不同的原因。

因为result是自动释放范围之外的强引用,ARC负责在退出池时保持活动状态,并且确实如此。你不需要做任何特别的事情。

更具体地说,ARC生成与此相当的代码:

void *_arp = objc_autoreleasePoolPush();
temp1 = objc_retainAutoreleasedReturnValue([self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]);
temp2 = objc_retainAutoreleasedReturnValue([temp1 stringByReplacingOccurrencesOfString:@"\"" withString:@"""]);
objc_release(temp1);
result = objc_retainAutoreleasedReturnValue([temp2 stringByReplacingOccurrencesOfString:@" " withString:@" "]);
objc_release(temp2);
// result is not released here
objc_autoreleasePoolPop(_arp);
return objc_autoreleaseReturnValue(result); // Result is returned autoreleased, or handed off to a  matching objc_retainAutoreleasedReturnValue() in the caller.

请注意,临时变量由objc_retainAutoreleasedReturnValue / objc_release对处理。由于objc_retainAutoreleasedReturnValueobjc_retainAutoreleasedReturnValue实现了运行时优化,这意味着临时值实际上会立即释放,而不会被放入自动释放池,如果 {{1}用ARC构建。我的猜测是,大多数系统框架还没有。

答案 3 :(得分:0)

为什么不在[[NSString alloc] initWithString:result]范围关闭之前使用@autoreleasepool?但为什么ARP首先在哪?