How to determine the protocol method is optional at runtime?

I have my protocol installed. I mentioned two of my protocol methods as optional. At runtime, how can I find out if a particular method is optional or not? Is there any way to find out?

+6
source share
2 answers

This should do what you want:

BOOL MethodInProtocolIsRequired(Protocol *protocol, SEL methodSelector) { struct objc_method_description methodDesc = protocol_getMethodDescription(protocol, methodSelector, YES, YES); return methodDesc.name != NULL; } 

Please note that I do not comment on the advisability of using this delivery code, especially since you did not explain why you want to do this. Also note that this function will return NO when specifying a selector for a method that the protocol does not contain. This is basically reasonable (after all, if the protocol does not contain a method, it is not required!), But you can add complexity to the function by checking if the protocol contains this method as an optional method and return something else for all three scenarios (required, optional, not in the protocol).

EDIT: A simple test program here: https://gist.github.com/4381753

+12
source

(I do not know the answer from the top of my head). 1 minute of the search query helped me.)

You can do this using the protocol_copyMethodDescriptionList() function, which is part of the Objective-C runtime library (libobjc). The second argument to this function is a boolean flag indicating whether methods that need to be copied in the protocol are needed. Thus, if the method is in the list returned by this function (called using the appropriate arguments), then this is the required method.

 SEL sctr = @selector(isThisMethod:requiredIn:theProtocol:); struct objc_method_description *methods; unsigned int nMethods; methods = protocol_copyMethodDescriptionList( objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName) if you don't need this kind of dynamism YES, // required? YES, // instance method? (in general, protocols declare instance methods) &nMethods ); BOOL isRequired = NO; int i; SEL s; const char *sctrStr = sel_getName(sctr); for (i = 0; i < nMethods; i++) { s = methods[i].name; const char *sStr = sel_getName(s); if (strcmp(sctrScr, sStr) == 0) { isRequired = YES; break; } } free(methods); if (isRequired) { // required } else { // optional } 

So it’s possible, but it’s a bit overkill, and as I mentioned in my comment on your question, you should not check that the method is optional or required, you should check the instance that responds to a specific selector.

Edit: yes, instead of copying the whole universe, I should have read further in the documentation. As Andrew Madsen noted, this can be summarized in a few lines:

 struct objc_method_description method; method = protocol_getMethodDescription( objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName) @selector(isThisSelector:required:) YES, // required? YES // instance method? ); if (method.name != NULL) { // required } else { // optional } 
+3
source

All Articles