在代码段示例中使用__autoreleasing

Gru*_*kes 1 ios

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

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

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

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

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

Col*_*lin 7

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

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

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[[NSError error] retain] autorelease]
}
Run Code Online (Sandbox Code Playgroud)

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

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[NSError alloc] init];
}
Run Code Online (Sandbox Code Playgroud)

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

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

*myError = [[[NSError error] retain] autorelease]
Run Code Online (Sandbox Code Playgroud)

在运行时.

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

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

  • @Norswap只是想象保存功能是预编译库的一部分.从save函数返回时,ARC需要知道错误对象(**myError)是否已存在于自动释放池中.在这种情况下,通过查看保存功能的源代码无法找到它,因为它没有它.它是关于保留ARC系统的输入.你不需要做同样事情的唯一原因(例如)myDict = [NSDictionary dictionary]),是因为有一个严格的约定,以这种方式返回的对象总是自动释放. (4认同)