I would like to know two things:
1- Is it possible by using objective-c introspection to know the return type of a block.
For example: int (^CountBlock)(NSArray *array)
I would like to know the type it will be returning is int
.
The second question is:
2- Can I hold a reference to a generic block? What I mean with this, is basically can I do something like id myBlock
and with this answer the first question.
What I tried
This kind of stuff is not possible:
id aBlock = ^{
NSString * aString = @"OMG";
return aString;
};
aBlock();
As the compiler sees that the id aBlock
is not a function or a function pointer.
1) This answer talks about how to grab the signature of a block. Here's the relevant code:
static const char *BlockSig(id blockObj)
{
struct Block *block = (void *)blockObj;
struct BlockDescriptor *descriptor = block->descriptor;
int copyDisposeFlag = 1 << 25;
int signatureFlag = 1 << 30;
assert(block->flags & signatureFlag);
int index = 0;
if(block->flags & copyDisposeFlag)
index += 2;
return descriptor->rest[index];
}
It's really not ideal, since you just get the @encode
string of the signature, which looks like this: @"i16@?0@8"
. I'd love to see if someone has a better approach.
2) You can definitely cast blocks to and from type id
:
typedef void(^MyBlockType)(void);
id aBlock = ^ { };
((MyBlockType)aBlock)();
Of course, if you cast to the wrong block type, you'll end up with undefined behavior.
I think the problem for number 2 is that blocks are named as part of the type definition, e.g.
void (^blockName)(void) = ^{};
A workaround is to define a generic block type:
typedef void(^BlockType)(void);
BlockType myBlock = ^{};
myBlock();
edit: pointed out by @neilco, a much simpler way using dispatch block types (which return nothing and accept no arguments):
dispatch_block_t myBlock = ^{};
myBlock();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With