0

苹果关于此事的文档指出:

复制块时,它会创建对块内使用的对象变量的强引用。如果在方法的实现中使用块:

如果通过引用访问实例变量,则会对 self 进行强引用;

如果您按值访问实例变量,则会对该变量进行强引用。

并且有代码示例:

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,它总是被引用。

那么这个例子不是太清楚他们的意思。为什么在第一种情况下是自我保留而在第二种情况下不是?它没有在任何地方使用,那么为什么要阻止捕获它呢?

4

1 回答 1

2

当您使用实例变量时,编译器会将您看到的 ivar 名称转换为self->iVar,这就是该块使用的内容。您甚至可以在您的代码中执行此操作 - 尝试访问带有self->前缀的内容。

编辑:所以在第一种情况下,块捕获self,因为它需要它来访问instanceVariable,如self-> instanceVariable. 因此,当块最终执行时,它将使用任何值。因为self是一个对象,所以它被保留。

在第二种情况下,一个临时变量(对象或非对象)被赋予 的当前值self-> instanceVariable,无论它当时是什么。当块捕获localVariable时,它会保留对象,并且在 dispatch_async 调用之后,ARC 会释放localVariable,所以块现在是唯一保留的东西localVariable。从那时起,该类可以更改实例变量,并且它对捕获的任何块都没有影响(一个例外 - 如果对象是可变对象,那么该块将在运行时使用任何内容 - 原因在这种情况下不要使用可变对象,而是使用非可变副本。

于 2013-06-06T15:46:58.997 回答