Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing Blocks in an Array

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?

like image 285
noizetoys Avatar asked Nov 03 '11 15:11

noizetoys


2 Answers

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.

like image 191
bbum Avatar answered Nov 04 '22 10:11

bbum


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.

like image 46
Eduardo Scoz Avatar answered Nov 04 '22 11:11

Eduardo Scoz