【问题标题】:Having trouble understanding Objective-C Block Documentation难以理解 Objective-C 块文档
【发布时间】:2013-01-05 23:31:06
【问题描述】:

我目前无法理解 Obj-C 块和 __block 存储类型的基础知识。 来自以下文档:

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

我正在尝试理解以下段落和示例:

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

如果通过引用访问实例变量,则会对自身进行强引用; 如果您按值访问实例变量,则会对该变量进行强引用。 以下示例说明了两种不同的情况:

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

要覆盖特定对象变量的此行为,您可以使用 __block 存储类型修饰符对其进行标记。

我的问题:

  1. 一个示例究竟是如何“通过引用访问”而另一个示例是通过变量访问?为什么 localVariable “按值使用”?
  2. 文档中的“强烈引用自我”是什么意思?它指的是哪个“自我”?
  3. 如果我在第二个示例中将 __block 存储类型添加到 localVariable 中,我是否错误地假设块关闭了变量,所以它将它保留在堆中直到块被释放?还发生了哪些其他事情?

谢谢!

【问题讨论】:

    标签: ios objective-c objective-c-blocks


    【解决方案1】:

    一个示例究竟是如何“通过引用访问”而另一个示例通过变量访问的?为什么 localVariable “按值使用”?

    一种理解方式如下:

    1. 当你在方法中定义的块中使用局部变量时,会发生什么情况是变量的内容被复制到某个块私有内存中,以便在执行块时(方法退出后)可用;从这个意义上说,我们可以谈论“按值”访问(如:值被复制);从语法上看,编译器不知道localVariable 的内容是指什么,所以它的值就是这样处理的;

    2. 当在类的方法中定义的块中直接访问instanceVariable时,编译器知道我们正在访问正在执行该方法的同一个对象并且不需要复制任何内容,因为该对象具有更长的生命周期比找到块的方法;但是我们需要确保块执行时对象仍然存在,因此我们得到了对它的强引用。

    现在,关于“通过引用”的使用:在第一种情况下,您会获得对类成员的引用的副本:如果您可以更改其值(但您不能,因为编译器禁止它),您只是修改了一个块私有副本,因此原始对象不受影响。

    在第二种情况下,您可以修改instanceVariable 的值(例如:它是nil,并且您分配了一个通过它引用的对象),这将影响执行该方法的对象,如果块被定义.

    文档中的“强烈引用自我”是什么意思?它指的是哪个“自我”?

    self 是当前正在执行找到块的方法的对象。进行强引用仅意味着(在 ARC 术语中)对象的保留计数会增加(以确保某些其他实体不能通过释放它来释放它)。

    如果我在第二个示例中将 __block 存储类型添加到 localVariable 中,我是否错误地假设块关闭了变量,因此它将它保留在堆中直到块被释放?还发生了哪些其他事情?

    使用__block 使变量始终“通过引用”访问,因此您可以修改它们。

    这是他们的处理方式:

    __block 变量存在于变量的词法范围和在变量的词法范围内声明或创建的所有块和块副本之间共享的存储中。因此,如果在帧中声明的块的任何副本在帧结束后仍然存在(例如,通过在某处排队以供稍后执行),则存储将在堆栈帧的破坏中幸存下来。给定词法范围内的多个块可以同时使用一个共享变量。

    作为一种优化,块存储从堆栈开始——就像块本身一样。如果块是使用 Block_copy 复制的(或者在 Objective-C 中,当块被发送一个副本时),变量被复制到堆中。因此,__block 变量的地址可以随时间变化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-12
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多