按值或引用访问变量

Pab*_*blo 5 objective-c objective-c-blocks

在下面的示例中,我不明白为什么localVariable要通过值访问doSomethingWithObject.是什么促成了转换?您如何区分按值访问变量和通过引用访问变量?如果可能的话,我想看到更多相关的例子.

以下是Apple的Blocks Programming Topics的摘录,并展示了如何在块中保留实例变量.

如果在方法的实现中使用块,则对象实例变量的内存管理规则更加微妙:

  • 如果通过引用访问实例变量,self则保留;
  • 如果按值访问实例变量,则保留变量.

以下示例说明了两种不同的情况:

dispatch_async(queue, ^{
    // instanceVariable is used by reference, self is retained
    doSomethingWithObject(instanceVariable);
});

id localVariable = instanceVariable;
dispatch_async(queue, ^{
    // localVariable is used by value, localVariable is retained (not self)
    doSomethingWithObject(localVariable);
});
Run Code Online (Sandbox Code Playgroud)

Dav*_*ong 12

这是因为当您直接访问实例变量时,编译器(或多或少)会将其转换为结构成员查找.所以:

[ivar doSomething];
Run Code Online (Sandbox Code Playgroud)

[self->ivar doSomething];
Run Code Online (Sandbox Code Playgroud)

因为self需要,self必须保留.但是,当您将指针值复制到新变量中时,您知道更长时间需要self结构知道指针值是什么,因此self不需要保留,因为指针值可以const从堆栈中复制.实例变量不会发生这种情况(因为ivar可能会在创建块和执行块之间发生变化).


澄清:

  • 块必须保留它在内部引用的所有对象,以确保这些对象在块的生命周期内将继续存在.
  • 当您直接在代码中访问ivar时,您实际上只是查找结构的成员(因为Objective-C对象实际上只是结构)
  • 查找结构的成员意味着你必须拥有结构
  • 因此,一个块将保留结构(在这种情况下self),以便查找始终成功.如果它没有这样做,那么self将来可能会被解除分配,现在结构查找会导致访问不当(很可能),你的应用程序会崩溃.
  • 或者,您可以在当前堆栈帧中本地创建新的对象指针.这样做的好处是您不再需要保留self,因为self不再涉及检索相关对象的地址
  • 当然,将保留局部变量引用的对象,以确保它在块的生命周期内存在.
  • 在这里使用"按值"和"按引用"这两个术语是完全错误的.Objective-C中的对象总是通过引用传递,因为我们总是传递指针.您无法在Objective-C中传递对象的值.(这里有一些注意事项,但你真的不想去那里)有关通过按值和按引用传递内容意味着什么的更多信息,请查看这个问题: 通过引用传递vs之间的区别是什么通过价值?