在_ ARC中使用__weak到局部变量

时间:2016-03-07 09:11:23

标签: ios objective-c memory-management automatic-ref-counting

在ARC中编写如下代码时

__weak NSMutableArray* array = [[NSMutableArray alloc] init];

编译器会显示警告或错误并说“将保留对象分配给弱变量。对象将在分配后释放”。

但如果你这样写:

__weak NSMutableArray* array = [NSMutableArray array];

没有错误。

我想知道在某些情况下第二次使用是否合理?从内存管理的角度来看,这两个代码有什么区别?它是如何工作的?

3 个答案:

答案 0 :(得分:1)

它们是相同的,因为你立刻失去了对象。除了alloc init之外,编译器可能无法知道对象是否会丢失。

答案 1 :(得分:1)

编译器无法知道可能存在非常微妙的差异。

让我们采用一个不可变的版本:[NSArray array]每次都可以返回相同的静态对象。所以你的弱变量将指向一个有效的对象,它在其他地方有一个强引用。或者想想单身人士模式。另一方面,当调用alloc/init时,约定规定你是该对象的唯一所有者,这通常会让你一无所有。

此外,工厂方法看起来更像是一种(功能)方法。在任何情况下,它都不会很好地传达它返回的所有权。对于自动发布的对象,目前尚不清楚您是唯一所有者还是共享所有者。

答案 2 :(得分:0)

在第一种形式中,该方法返回保留的对象。 ARC确保在呼叫站点上没有强引用时释放对象。这是立即 true,带有弱引用 - 因此,编译器会发出警告或错误。

在第二种形式中,该方法返回未保留的对象。在这种情况下,编译器必须确保对象在返回边界上仍然有效。当从这样的函数或方法返回时,ARC在返回语句的评估点保留该值,然后保留所有本地范围,然后平衡保留,同时确保该值跨越调用边界。也就是说,编译器创建了一个强引用。这个强引用将由编译器生成的代码自动发布。

因此,在这种情况下,没有错误或警告。

在最坏的情况下,持有该对象可能需要使用自动释放池。但是,编译器可以应用某些优化来避免这种情况。因此,我们不应该假设返回的对象存在于自动释放池中。

参见规范:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14

另见SO上的这个问题:Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]