Now on GitHub, WoolBlockInvocation !
These are a couple of the WSSBlockInvocation and WSSBlockSignature along with some supporting code that use libffi and the ObjC @encode @encode that the compiler generates for blocks so you can call up a complete list of blocks with the same set of arguments.
Any number of blocks can be added to the call object if their signatures - the value of the return type, the number and types of arguments - match. After setting the arguments of the call invocation object, the locks can be called in turn, and the return values, if any, are stored for later access.
The piece that you are particularly interested in stitching this list of blocks into one block is provided by the invocationBlock method of WSSBlockInvocation .
- (id)invocationBlock { return [^void (void * arg1, ...){ [self setRetainsArguments:YES]; va_list args; va_start(args, arg1); void * arg = arg1; NSUInteger numArguments = [blockSignature numberOfArguments]; for( NSUInteger idx = 1; idx < numArguments; idx++ ){ [self setArgument:&arg atIndex:idx]; arg = va_arg(args, void *); } va_end(args); [self invoke]; } copy]; }
This returns a block that (ab) uses varargs to defer the assignment of arguments until this encapsulating block actually calls itself. So you can do the following:
WSSBlockInvocation * invocation = [WSSBlockInvocation invocationWithBlocks:@[animationBlockOne, animationBlockTwo]]; void (^combinedAnimation)(void) = [invocation invocationBlock]; [UIView animateWithDuration:1 animations:combinedAnimation];
Of course, if you just worry about blocks for animations that take no arguments and have no return value, then creating a wrapper block is trivial:
void (^combinedAnimation)(void) = ^{ animationBlock(); anotherAnimationBlock();
You only need my code if you need to wrap a set of blocks and call them all with the same set of arguments.
NB I tested this on OS X on x86_64, but not on any other platform . I hope that it works on ARM under iOS, but varargs is cool "not portable", and this may not be the case. Compile a compiler and let me know if something breaks.