0

Apple documentation on this matter states:

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.

and there is code example:

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

});

But to me it makes no sense. How can you access instance variable by value? Don't you always access it via reference? Be it self.myVariable or just id newName = self.myVariable, it is always by reference.

Then this example is not too clear what they mean. Why is in first case self retaind and in second case not? It's not used anywhere, so why would block capture it?

MegaManX
  • 8,766
  • 12
  • 51
  • 83

1 Answers1

2

When you use an instance variable, the compiler turns what you see as the ivar name into self->iVar, and that's what the block uses. You can even do this in your code - try accessing something with self-> prepended.

EDIT: So in the first case, the block captures self, because it needs it to access instanceVariable, as in self-> instanceVariable. Thus, it will use whatever the value is when the block finally executes. Since self is an object, it gets retained.

In the second case, a temporary variable (object or not) is assigned the current value of self-> instanceVariable, whatever it is at that moment. When the block captures localVariable, it retains the object, and just after the dispatch_async call, ARC releases localVariable, so the block now is the only thing retaining localVariable. From then on, the class can change the instance variable and it will have no affect on whatever the block captured (one exception - if the object is a mutable object, then the block will use whatever the contents are when it runs - the reason to NOT to use mutable objects in this situation, but to use a non-mutable copy.

David H
  • 40,852
  • 12
  • 92
  • 138
  • Thanks for the effort and time for trying to answer, but did you read my questions? I think a little more info is needed. – MegaManX Jun 07 '13 at 07:53
  • One more question, if we wrote __weak id localVariable, would the block still retain the localVariable? – MegaManX Jun 07 '13 at 13:41
  • 1
    No. The way to do this is create a weak variable "weakSelf" - see http://clang.llvm.org/docs/AutomaticReferenceCounting.html. I wrote a blog on weakSelf and strongSelf, and now to do more complex blocks: http://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/ - it references the llvm site above and tells you the chapter this is mentioned on. – David H Jun 07 '13 at 14:46