It is not clear to me whether the question is about the lifetime of the block, as per the title, or the lifetime of the object referenced by myObject
, so we'll cover both.
First, the stack allocation of blocks in an optimisation and something programmers should not really need to be aware of. Unfortunately when blocks were first introduced the compiler was not smart enough to handle this optimisation completely automatically, hence the need to know about Block_copy()
etc. But the compiler is now much smarter and the programmer can pretty much forget about stack allocation of blocks.
This answer applies to Xcode 5.0.2/Clang 4.2. Use a different (earlier) version and YMMV.
Second, the block:
^{ NSLog(@"Something Happened"); }
is not actually stack allocated at all. As it references no values from the environment it is statically allocated and never needs to be placed on the stack or moved to the heap - another optimisation. To get a stack allocated block just change it to:
^{ NSLog(@"Something Happened: %p", self); }
which will be stack allocated (and don't worry about possible retain cycles, that's another topic...)
With that out of the way, let's look at the lifetimes:
The object:
The variable myObject
has a lifetime of at most the call to viewDidLoad
, the variable is created on entry to the method and destroyed on exit, if precise lifetime semantics are in force, or earlier if not needed and precise lifetime semantics are not in force - the latter is the default allowing the compiler to optimise storage use (independent of ARC). By default local variables have a strong ownership qualifier, so an ownership interest is asserted for any reference stored in one. ARC will release that ownership interest when another reference is stored in the variable or when the variable itself is destroyed. The latter will happen in this case and the variable is destroyed at some time after the last use of it and the end of the method - depending on how the compiler does its optimisations.
All this means that the object referenced by myObject
may or may not be still around at your call to NSLog()
. In the case of using performSelector:withObject:afterDelay:
that call will assert ownership over the object until after the selector has been executed -= so the object will live. In the case of using dispatch_after
the object is not required and so will not stay alive.
The block:
As mentioned above as written the block is statically allocated so lifetime is easy - it always exists. More interesting is modifying it as above to make it stack allocated.
If the block is stack allocated it will exist in the stack frame of the viewDidLoad
call and unless moved or copied to the heap it will disappear when that call returns.
The call to doSomethingWithBlock:
will be passed a reference to this stack allocated block. This is possible as doSomethingWithBlock:
expects a block and code within it can move it to the heap if needed as it knows it is a block.
Now it gets interesting. Within doSomethingWithBlock:
in the performSelector:withObject:afterDelay:
case the block is passed as the withObject:
parameter which is of type id
- which means the called code expects a standard Objective-C object and those live on the heap. This is a case of type information loss, the caller has a block, the callee only sees an id
. So at this point the compiler inserts code to copy the block to the heap and passes that new heap block to performSelector:withObject:afterDelay:
- which treats it as it would any other object. [Older compilers did not always do this, the programmer had to know that type information loss was about to occur and manually insert code to move the block to the heap.]
In the case of dispatch_after
, the function argument is block typed so the compiler just passes a stack allocated block on. However the dispatch_after
function copies the block to the heap, as per its documentation, and there is no problem.
So in either case a stack allocated block is copied to the heap before viewDidLoad
finishes and its stack frame is destroyed taking with it the stack allocated block.
HTH.