Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having trouble understanding Objective-C Block Documentation

I'm currently having trouble understanding the fundamentals of Obj-C blocks and the __block storage type. From the following documentation:

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

I'm trying to understand the following paragraph and examples:

When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:

If you access an instance variable by reference, a strong reference is made to self; If you access an instance variable by value, a strong reference is made to the variable. The following examples illustrate the two different situations:

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

To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.

My questions:

  1. How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"
  2. What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?
  3. 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?

Thank you!

like image 921
SChang Avatar asked Jan 22 '13 16:01

SChang


1 Answers

How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"

One way to understand this is the following:

  1. when you use a local variable in a block defined in the method, what happens is that the content of the variable is copied in some block private memory, so that it is available when the block is executed (after the method exits); in this sense we may talk of accessed "by value" (as in: the value is copied); syntactically the compiler doesn't know what the content of localVariable refers to, so its values is treated as such;

  2. when directly accessing instanceVariable in a block defined within a method of a class, the compiler knows that we are accessing the same object that is executing the method and there is not need to copy anything, since the object has a longer lifetime than the method where the block is found; but we need to ensure that the object is still there when the block is executed, so we get a strong reference to it.

Now, as to the use of "by reference": in the first case, you get a copy of the reference to the class member: if you could change its value (but you can't, because the compiler forbids it), you were just modifying a block private copy, so the original object is not affected.

In the second case, you can modify the value of instanceVariable (like in: it was nil and you allocate an object referred through it) and this will affect the object that executed the method were the block is defined.

What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?

self is the object which is currently executing the method where the block is found. that a strong reference is made only means (in ARC parlance) that the retain count of the object is incremented (to make sure some other entity cannot cause it to be deallocated by releasing it).

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?

Using __block makes the variable be always accessed "by reference", so you can modify them.

This is how they are handled:

__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.

like image 59
sergio Avatar answered Sep 21 '22 08:09

sergio