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.
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.
精彩评论