Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a general directly executable type for Objective-C blocks?

I’d like to get rid of the complex type declaration before my one-shot blocks:

void (^blockHelperA)(NSString*, NSString*) = ^(NSString *foo, NSString *bar) {…};

This could be rewritten as:

id blockHelperB = ^(NSString *foo, NSString *bar) {…};

Which looks better and compiles, but can’t be directly executed:

// “Called object type 'id' is not a function or function pointer”
blockHelperB(@"Foo", @"Bar");

Then there’s a dispatch_block_t type, but that’s just a simple shorthand:

typedef void (^dispatch_block_t)(void);

Is there a way to get rid of the precise type declaration and still execute the block afterwards in a simple way? I know I can do this:

id foo = ^{ return @"bar"; };
dispatch_sync(dispatch_get_current_queue(), foo);

…but that just shifts the noise from the declaration to execution.

like image 825
zoul Avatar asked May 19 '11 07:05

zoul


1 Answers

There is no (sane) way to do this as you are restricted by C's type system.

For function pointers and blocks in particular, C will not allow you to define a "generic" type.

An example of this is that the type dispatch_block_t will only work with blocks that have a void return type and zero arguments. No other block signature will work. Period.

Since blocks are effectively transformed into function pointers at compile time (among other magic), there is no direct type associated with them. Your mileage may vary greatly as to the actual type of block that you have stored in any given block reference. So, with this in mind, you can understand why the compiler doesn't understand you when you try to store a block in an id.

More information on this can be found here: http://clang.llvm.org/docs/Block-ABI-Apple.html.

Sorry, but this is just one of those quirks that you will have to learn to live with.

like image 178
Jacob Relkin Avatar answered Jan 01 '23 08:01

Jacob Relkin