0

I'm trying to get the signature of a block in a Protocol method.

Here's a sample protocol:

@protocol ProtocolSample <NSObject>
- (void) doSomething: (void (^) (NSString *))a_block;
@end

I am able to get the signature of doSomething using the following:

Protocol *protocol_sample = @protocol(ProtocolSample);

unsigned int outCount;
struct objc_method_description *method_description_list = protocol_copyMethodDescriptionList(protocol_sample, YES, YES, &outCount);

struct objc_method_description method_description = method_description_list[0];

NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:method_description.types];

The signature I get is: v@:@?

My goal is to get the signature of the a_block. I've tried many methods including the following:

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

void *block;
[invocation getArgument:&block atIndex:2];

But block is always NULL.

How is it possible to get the signature of a_block?

  • A Block is an object, so `@` is correct. Have a look at my answers to similar questions: https://stackoverflow.com/a/36162832/603977 and https://stackoverflow.com/a/17892240/603977 – jscs Feb 19 '19 at 22:12
  • @JoshCaswell Unfortunately, it does not work. I tried `WSSBlockInvocation * block_invocation = [WSSBlockInvocation invocationWithSignature:[WSSBlockSignature signatureForBlock:(__bridge id)(block)]];` where `block` is from the question text above. It gives an `EXC_BAD_ACCESS` because `block` is NULL. – user11086841 Feb 19 '19 at 22:22
  • Yes, you need an actual instance of the Block to use `signatureForBlock:` – jscs Feb 19 '19 at 22:23
  • @JoshCaswell How can I do that? I've been stuck on this issue for days :/ – user11086841 Feb 19 '19 at 22:26
  • Can you explain _why_ you're trying to do this? It might help; there might be another way. – jscs Feb 19 '19 at 23:13
  • I have a list of protocols (100s) with methods that’d I’d like to get the signature for (instead of doing it manually). I know this functionality does exist but I’m not sure how to do it. – user11086841 Feb 19 '19 at 23:19
  • Instead of doing _what_ manually? What do you actually need the signature for? – jscs Feb 19 '19 at 23:21
  • Instead of manually looking at each method and determining its protocol. I can technically make a python script that reads the header file and determine the signature, but I’d like to do this natively in Obj-C. I just want to be able to do it for the sake of learning and maybe use it in the future if needed. – user11086841 Feb 19 '19 at 23:51
  • @JoshCaswell See my answer below. One function got the job done :) – user11086841 Feb 20 '19 at 16:02
  • Cool, nice find! – jscs Feb 20 '19 at 18:43

2 Answers2

1

Finally found the answer: const char *_protocol_getMethodTypeEncoding(Protocol *, SEL, BOOL isRequiredMethod, BOOL isInstanceMethod);

The method will get you the full signature of any selector!

0

There is also

extern const char* _Block_signature(id block);

which you can use for any arbitrary block object.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • I tried using `_Block_signature` but it doesn't work. Do I have to import some framework to find it? I tried googling this function but I'm not finding anything, and Apple's doc turn up nothing. – Augusto Dias Noronha Feb 17 '20 at 14:11