objective-c - 按值或引用访问变量

标签 objective-c objective-c-blocks

在下面的示例中,我不明白为什么 localVariable 是通过 doSomethingWithObject 中的值访问的。是什么导致了这种转变?如何区分按值访问变量和按引用访问变量?如果可能,我希望看到更多相关示例。

以下是 Apple 的 Blocks Programming Topics 的摘录并显示实例变量如何保留在 block 中。

If you use a block within the implementation of a method, the rules for memory management of object instance variables are more subtle:

  • If you access an instance variable by reference, self is retained;
  • If you access an instance variable by value, the variable is retained.

The following examples illustrate the two different situations:

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);
});

最佳答案

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

[ivar doSomething];

成为

[self->ivar doSomething];

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


澄清:

  • block 必须保留它在内部引用的所有对象,以确保这些对象在 block 的生命周期内继续存在。
  • 当您直接在代码中访问 ivar 时,您实际上只是在查找结构的成员(因为 Objective-C 对象实际上只是结构)
  • 查找一个结构的成员意味着你必须拥有该结构
  • 因此, block 将保留结构(在本例中为 self),以便查找始终成功。如果它不这样做,那么 self 将来可能会被释放,现在结构查找会导致错误访问(很可能)并且您的应用程序会崩溃。
  • 或者,您可以在当前堆栈帧中本地创建一个新的对象指针。这样做的好处是您不再需要保留 self,因为 self 不再参与检索相关对象的地址
  • 当然,局部变量引用的对象将被保留,以确保它在 block 的生命周期内存在。
  • 在此处使用术语“按值”和“按引用”是完全不正确的。 Objective-C 中的对象总是通过引用传递,因为我们总是传递指针。您不能在 Objective-C 中按值传递对象。 (对此有一些注意事项,但您真的不想去那里)有关按值传递与按引用传递的含义的更多信息,请查看以下问题:What's the difference between passing by reference vs. passing by value?

关于objective-c - 按值或引用访问变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6433348/

相关文章:

objective-c - 在 Objective-C 中从异步 block 增加变量

iphone - block 和 ViewController 线程安全

objective-c - ios - UIActivityIndi​​catorView 是否应该默认显示?

iphone - 如何让 iPhone 振动?

iphone - 如何动态调整 scrollViewDidZoom 中的 contentInset?我最初在 UIScrollview 中设置了 UIImageView 的 contentInset

ios - UIKeyboardTaskQueue 线程问题

ios - 安排任务在 phonegap ios 中的特定时间运行?

objective-c - 保持对象事件直到后台任务完成

objective-c - 获取 NSButton 上的悬停事件以显示图像

objective-c - Swift 中的飞利浦 HUE SDK