关于此事的Apple文档声明:
复制块时,会创建对对象的强引用 块内使用的变量。如果你在里面使用一个块 方法的实施:
如果通过引用访问实例变量,则引用强引用 为自己做的;
如果按值访问实例变量,则强引用 对变量做了。
并且有代码示例:
dispatch_async(queue, ^{
// instanceVariable is used by reference, a strong reference is made to self
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
/*
localVariable is used by value, a strong reference is made to localVariable
(and not to self).
*/
doSomethingWithObject(localVariable);
});
但对我来说没有任何意义。如何按值访问实例变量?你总是通过参考访问它吗?无论是self.myVariable
还是id newName = self.myVariable
,都始终是参考。
然后这个例子不太清楚他们的意思。为什么在第一种情况下自我保留,在第二种情况下不是?它没有在任何地方使用,所以为什么要阻止它?
答案 0 :(得分:2)
当您使用实例变量时,编译器会将您看到的ivar名称转换为self->iVar
,这就是该块使用的内容。您甚至可以在代码中执行此操作 - 尝试访问前缀为self->
的内容。
编辑:所以在第一种情况下,该块会捕获self
,因为它需要它来访问instanceVariable
,就像self-> instanceVariable
一样。因此,它将使用块最终执行时的任何值。由于self
是一个对象,因此会被保留。
在第二种情况下,临时变量(对象与否)被赋予当前值self-> instanceVariable
,无论当时是什么。当块捕获localVariable
时,它会保留对象,并且在dispatch_async调用之后,ARC释放localVariable
,因此块现在是唯一保留localVariable
的块。从那时起,类可以更改实例变量,它不会影响捕获的块(一个例外 - 如果对象是一个可变对象,那么块将使用它运行时的任何内容 - 原因是在这种情况下不要使用可变对象,而是使用不可变副本。