在代码段示例中使用__autoreleasing

时间:2012-02-29 15:41:46

标签: ios

以下代码摘自“iOS 5 Developer's Cookbook”,用于说明如何将字符串写入文件。它使用了__autoreleasing而没有任何解释。为什么有必要?

NSError __autoreleasing error;
...
if (![myString writeToFile:path atomically:YES error:&error)
{
    NSLog(.... error.localizedFailureReason  ...);
    return;
}

为什么不在不使用__autoreleasing的情况下在堆栈上声明错误?

------编辑-----

附加问题:为什么作者声明NSError而不是NSError *?

5 个答案:

答案 0 :(得分:7)

当一个变量通过引用传递并在ARC程序中分配时,您错过了此代码中实际发生的情况。例如,一个函数(BOOL)保存:(NSError * __autoreleasing *)错误

在非ARC编程中,保存功能如下所示:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[[NSError error] retain] autorelease]
}

在ARC编程中,保存功能如下所示:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[NSError alloc] init];
}

尽管ARC代码看起来如此,但两个保存函数都会创建一个已保留并自动释放的错误对象。

这是因为在ARC版本中,myError指针的类型决定了错误对象的内存管理会发生什么。实际上,只要指针是__autoreleasing类型,* myError赋值行被替换并带有

*myError = [[[NSError error] retain] autorelease]

在运行时。

因此,如果我们能以某种方式将错误类型的指针传递给保存函数,例如__strong,则会导致save函数执行错误操作。

由于编译器会通过创建临时变量来防止这种情况发生,因此代码将以任何一种方式工作,但是从ARC编程的角度来看,传入一个非__autoreleasing类型的指针是没有意义的。

答案 1 :(得分:3)

它提示自动参考计数(ARC)系统。

error对象将在NSString的代码中的某处分配,因此在代码中将其声明为__autoreleasing,ARC可以知道存储特性是什么。也就是说,当设置error时,它将是一个自动释放的对象。

答案 2 :(得分:2)

来自https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html的ARC发行说明:

  

__ autoreleasing用于表示通过引用(id *)传递的参数,并在返回时自动释放。

当你声明变量时会产生__strong的隐式声明,但由于它是通过引用传递的,所以编译器需要提示才能做正确的事情。它是否是堆栈变量不会影响保留/释放跟踪。

答案 3 :(得分:1)

代码:

__autoreleasing  NSString *str = xx;

将由ARC编译为:

NSString *str = xx.autorelease

答案 4 :(得分:0)

嗯,对于通过引用传递的对象,使用__autoreleasing限定符是一种ARC约定。解释来自clang网站:

  

4.3.2。 __autoreleasing对象的存储持续时间

     

如果程序声明__autoreleasing对象,则该程序格式错误   非自动存储时间。

     

基本原理:自动释放池与当前线程和范围相关联   就其性质而言。虽然有可能有临时对象   实例变量用自动释放的对象填充,没有   ARC可以在那里提供任何形式的安全保障。

     

如果为a分配了非空指针,则为未定义的行为   __autoreleasing对象,而自动释放池在范围内,然后在自动释放池的范围被删除后读取该对象。