Storing Blocks in an Array

Objective CMemory ManagementObjective C-Blocks

Objective C Problem Overview


In Objective-C, I know that blocks are considered objects, so I was wondering if it was possible to store them in an array. This begs the question, are blocks first class objects or are they just treated like objects for the sake of passing them between objects? If they are first class objects, then shouldn't they be storable in arrays?

Objective C Solutions


Solution 1 - Objective C

> EDIT: Without going into too much detail, under ARC, you can now add blocks to collections like any other object (see discussion).

I've left the original answer intact below, since it contains some interesting technical details.


> This begs the question, are blocks first class objects or are they > just treated like objects for the sake of passing them between > objects? If they are first class objects, then shouldn't they be > storable in arrays?

Blocks are Objective-C objects that very much behave like every other NSObject, with a couple of key differences:

  • Blocks are always generated by the compiler. They are effectively "alloc/init"ed at runtime as execution passes over the blocks declaration.

  • Blocks are initially created on the stack. Block_copy() or the copy method must be used to move the Block to the heap if the Block is to outlive the current scope (see ARC point below).

  • Blocks don't really have a callable API beyond memory management.

  • To put a Block into a Collection, it must first be copied. Always. Including under ARC. (See comments.) If you don't, there is risk that the stack allocated Block will be autoreleased and your app will later crash.

  • Copying a stack based block will copy all of the captured state, too. If you are making multiple copies of a block, it is more efficient to copy it once, then copy the copy (because copying the copy just bumps the retain count since Blocks are immutable).

  • Under ARC, returning a Block from a method or function "just works"; it'll be automatically copied to the heap and the return will effectively be an autoreleased Block (the compiler may optimize away the autorelease in certain circumstances). Even with ARC, you still need to copy the block before sticking it into a collection.

I've written a couple of blog posts both providing an introduction to blocks and some tips and tricks. You might find them interesting.

And, yes, adding 'em to dictionaries is quite useful. I've written a couple of bits of code where I dropped blocks into dictionaries as command handlers where the key was the command name. Very handy.

Solution 2 - Objective C

Yes, blocks are indeed objects, and you can put them in arrays:

NSMutableArray *arr = [NSMutableArray new];
[arr addObject:^(){NSLog(@"my block");}];
void (^ myblock)() = [arr objectAtIndex:0];
myblock();

this will put the "my block" in the console.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnoizetoysView Question on Stackoverflow
Solution 1 - Objective CbbumView Answer on Stackoverflow
Solution 2 - Objective CEduardo ScozView Answer on Stackoverflow