Attack the Block

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.