I want to dynamically add code to a block variable, or merge or concatenate a block with another block. Is this possible?
Asked
Active
Viewed 601 times
3
-
possible duplicate of [What happens to a block at compile time, and can I create one at runtime?](http://stackoverflow.com/questions/16323089/what-happens-to-a-block-at-compile-time-and-can-i-create-one-at-runtime) – Caleb Jan 28 '14 at 18:25
3 Answers
5
One way of doing it is creating a block that calls the block to be "expanded" before performing its own functions.
For example, consider the example below that adds logging functionality to an arbitrary block passed into it:
typedef void (^MyBlock)(int);
-(MyBlock) expand:(MyBlock)nested {
return ^(int x) {
nested(x);
NSLog("The value of x = %d", x);
};
}
The cumulative effect of calling the block produced by expand:
is that of invoking the original block, followed by an operation from the expanded block. You can take it further, to create an appendBlock
method:
-(MyBlock) appendBlock:(MyBlock)second toBlock:(MyBlock)first {
return ^(int x) {
first(x);
second(x);
};
}

Sergey Kalinichenko
- 714,442
- 84
- 1,110
- 1,523
3
Is this possible?
No, but you can create a collection of blocks and execute them sequentially.

Caleb
- 124,013
- 19
- 183
- 272
-
Would you give an example of assigning a block to a collection? Would it need to be a c-array since a block is not an obj? Or can you somehow wrap a block within another object for storage into a NSMutableArray? – eric Jan 28 '14 at 18:30
-
1No wrapping required -- [a block is an Objective-C object](https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/bxOverview.html#//apple_ref/doc/uid/TP40007502-CH3-SW2). You can [store them in an NSArray](http://stackoverflow.com/q/7997666/643383) (or other Obj-C collection), or you can create another block that takes two or more blocks as parameters and executes them one after another, as dasblinkenlight has nicely illustrated. – Caleb Jan 28 '14 at 19:42
-
How can we know when the block at index n has completed so that we can move onto n+1? – eric Jan 30 '14 at 16:15
-
1I think you're thinking that blocks always run asynchronously, but that's not the case at all. If you have a block assigned to a variable, you can invoke the block using the variable just like you would with a function pointer: `for (MyBlockType someBlock in listOfBlocks) { someBlock(); }` Async execution really only happens if you run the block on another thread or queue, like when you use GCD's `dispatch_async()` function to invoke the block. – Caleb Jan 30 '14 at 17:08
-
1you had me at 'i think youre thinking that blocks always run asynchronously' ;) – eric Jan 30 '14 at 18:11
1
Sure - just create a new block, which makes use of the original in whatever compositional way you'd like. If you've got block1
and block2
, you might create:
someCodeBefore = ^myBlockType(block1) {
someCode()
thatIWantBefore();
block1();
}
someCodeAfter = ^myBlockType(block1) {
block1();
someCode()
thatIWantAfterBlock1();
}
composedBlocks = ^myBlockType(block1, block2) {
block1();
block2();
}
Just make sure you're copying the blocks correctly.

Adam Wright
- 48,938
- 12
- 131
- 152
-
That's really not the same as merging/concatenating blocks together. You still have separate blocks, each with its own state, rather than a single block with shared state. – Caleb Jan 28 '14 at 18:26
-
But, as blocks are opaque, what would it mean to "share state"? You couldn't see any of it even if it were shared. – Adam Wright Jan 28 '14 at 18:41
-
Exactly -- you can use blocks in combination, and you can have a single block that contains other blocks, but you can't *merge* two blocks into a single block (which is what I understood the OP to be asking about). – Caleb Jan 28 '14 at 19:21