http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6
我试图理解以下段落和示例:
复制块时,它会创建对块中使用的对象变量的强引用.如果在方法的实现中使用块:
如果通过引用访问实例变量,则会对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); });
要覆盖特定对象变量的此行为,可以使用__block存储类型修饰符对其进行标记.
我的问题:
>一个例子如何“通过引用访问”,而另一个例子是通过变量访问的?为什么localVariable“按价值使用?”
>该文件的意思是“强烈参考自我”?它指的是哪个“自我”?
>如果我在第二个例子中将__block存储类型添加到localVariable,我错误地假设该块关闭了变量,所以它将它保留在堆中直到块被释放?还有其他什么事情发生?
谢谢!
解决方法
How exactly is one example “accessed by reference” while the other one is accessed by variable? Why is localVariable “used by value?”
了解这一点的一种方法如下:
>当在方法中定义的块中使用局部变量时,会发生的变化是将变量的内容复制到某个块专用内存中,以便在执行块时(在方法退出后)可用;在这个意义上,我们可以谈论“按价值”访问(如:复制值);从语法上讲,编译器不知道localVariable的内容是指什么,所以它的值被视为这样;
>当直接访问类的方法中定义的块中的instanceVariable时,编译器知道我们正在访问执行该方法的同一对象,并且不需要复制任何东西,因为该对象的生命周期比方法长找到块的位置;但是我们需要确保在执行块时对象仍然存在,因此我们得到了一个强引用.
现在,关于“引用”的使用:在第一种情况下,你得到了对类成员的引用的副本:如果你可以改变它的值(但你不能,因为编译器禁止它),你只是修改一个块私有副本,所以原始对象不受影响.
在第二种情况下,您可以修改instanceVariable的值(例如:它是nil并且您分配了一个通过它引用的对象),这将影响执行该方法的对象是否已定义块.
What does the doc mean by “a strong reference is made to self”? Which “self” is it referring to?
self是当前正在执行找到块的方法的对象.强引用只是意味着(在ARC的说法中)对象的保留计数增加(以确保某些其他实体不能通过释放它来解除分配它).
If I add the __block storage type to localVariable in the second example,am I wrong to assume that the block closes over the variable,so it keeps it around in heap until block is released? What other things are happening?
使用__block使变量始终“通过引用”访问,因此您可以修改它们.
这是他们的处理方式:
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus,the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example,by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.
As an optimization,block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy),variables are copied to the heap. Thus,the address of a __block variable can change over time.