How many readers of this blog know that Objective-C blocks are initially created on the stack, unlike every other type of Objective-C object? I believe this is for performance reasons.
It used to be a bigger deal, before ARC. Why? Because those stack-based blocks would be deallocated once their scope ended. If you tried to reference a stack-based block outside its enclosing scope, your app would crash and burn.
To get around this, you had to send a copy
message to the block, which would perform a special sort of copy to copy it to the heap instead, like every other Objective-C object. Then it could be passed around, because it wasn’t tied to the stack’s scope anymore. Of course, then you’d also be on the hook for sending it a release
message, or you’d have a memory leak.
That’s why, if you have a block property, you’re supposed to use the copy
attribute, not the retain
(now strong
) attribute:
typedef void (^MyBlock)(); @interface MyClass : NSObject @property (nonatomic, copy) MyBlock myBlock; @end
All that’s water under the bridge with ARC, however.
ARC adds those copy
calls for you, in the same way that it adds retain
and release
calls for regular Objective-C objects. You’ll never have to worry about using a stack-based block outside of its scope accidentally, because ARC will never let you do that.
The result? Now, when I mention the dangers of stack-based blocks to my younger coworkers, they have no idea what I’m talking about.