2012-02-29 70 views
1

下面的代码是从用来说明如何写一个字符串到文件“的的iOS 5开发者的食谱”拍摄。它利用__autoreleasing没有任何解释。为什么有必要?使用代码__autoreleasing的片断例如

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

为什么不直接在堆栈上声明错误而不使用__autoreleasing?

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

另一个问题:为什么作者声明NSError而不是NSError *?

回答

3

这对自动的引用计数(ARC)系统的暗示。

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

+0

大多数时候NSError被声明为NSError *错误。但在这种情况下,它的NSError错误。即在wrieToFile之前创建NSError:这是否会产生后果? – Gruntcakes 2012-02-29 16:28:22

+0

我实际上用'NSError * error'提交了一个编辑到你原来的问题。我认为这一定是本书中的一个错字:Obj-C对象总是用指针引用,所以'NSError error'会给编译时错误。 – gregheo 2012-02-29 17:05:17

+0

恐怕这个答案是不正确的。它不是“提示”,而是语义的声明 - *提示*可以忽略,*语义*不可以。另外,存储的引用不需要对自动释放的对象进行存储。请参阅[这个问题](http://stackoverflow.com/questions/8814718/handling-pointer-to-pointer-ownership-issues-in-arc)了解更多的背景知识。 – CRD 2014-04-22 18:54:06

0

嗯,这是一个ARC约定使用__autoreleasing预选赛按引用传递对象。 【解说】这里离铛网站:

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

是形成不良的一种程序,如果它声明 非自动存储持续时间的__autoreleasing对象。

理由:自动释放池被绑定到其本质当前线程和范围 。虽然可能有临时对象,其 实例变量都充满了自动释放的对象,没有 方式,ARC能提供任何安全保障的存在。

这是,如果一个非空指针被分配给 __autoreleasing对象,同时自动释放池是在范围上,然后自动释放池的范围离开后该对象被读取未定义的行为。

1

代码:

__autoreleasing NSString *str = xx; 

将ARC被编译为:

NSString *str = xx.autorelease 
+0

没有属性的点语法不是最佳实践。除此之外,它并没有真正回答为什么在ARC – Binarian 2013-08-11 19:51:50

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保存函数,它会导致保存函数做错误的事情。

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

+0

中使用[xx autorelease]这是一个很好的答案,这是唯一真正解释引擎盖下发生的问题的答案之一。我还有一个额外的问题。为什么要传递给'save'的地址需要声明为'__autoreleasing'? ARC转换指南说,否则会弹出一个临时变量,但是编译器不能对此做出明智的判断?或者是否存在这个问题的语义原因? – Norswap 2013-11-27 10:36:41

+4

@Norswap试想一下,保存函数是预编译库的一部分。当你从保存功能返回时,ARC需要知道错误对象(** myError)是否已经在自动释放池中。在这种情况下,通过查看保存功能的源代码找不到它,因为它没有它。这是关于保存对ARC系统的输入。当你这样做时(例如)myDict = [NSDictionary dictionary]),你不需要同样的东西的唯一原因是因为严格约定,以这种方式返回的对象总是自动释放。 – Colin 2013-12-02 18:20:34

+0

我想上面的评论更直接地回答OP的问题,而不是上面的答案。在回答这个问题时,我感兴趣的是,ARC实际上是在程序员明确处理ARC之前做了与幕后相同的事情。它是智能编译器的一部分,不属于新的运行时引擎。 – Colin 2013-12-02 18:26:28