8

There is an -[NSObject conformsToProtocol:] method to check whether a specific protocol is adopted or not. Is there any method to get all adopted protocols for a class, rather than checking a list?

jscs
  • 63,694
  • 13
  • 151
  • 195
Shaheer Palolla
  • 265
  • 4
  • 11
  • 1
    What exactly are you trying to accomplish with this? – Richard J. Ross III Jun 12 '13 at 17:42
  • @RichardJ.RossIII I've often used protocol conformance where I need some general object to be able to pick and then dispatch work to an appropriate target (eg, a universal `UITableViewDataSource` to be able to pick an appropriate cell for a given object and then set that object); I judge that it's more maintainable and requires less redeclaration for the dispatcher to find appropriate targets via the runtime and then query them as to what they'll expect. Any thoughts on that pattern? – Tommy Jun 12 '13 at 20:49

3 Answers3

12

There's a more elegant solution: class_copyProtocolList() directly returns the adopted protocols of a class. Usage:

Class cls = [self class]; // or [NSArray class], etc.
unsigned count;
Protocol **pl = class_copyProtocolList(cls, &count);

for (unsigned i = 0; i < count; i++) {
    NSLog(@"Class %@ implements protocol <%s>", cls, protocol_getName(pl[i]));
}

free(pl);
  • 3
    One should only keep in mind that this list does not contain the protocols adopted by the superclasses, so - depending on what this list is used for - it might be necessary to walk up the superclass chain and call class_copyProtocolList() again. – Martin R Jun 12 '13 at 21:53
  • @MartinR Exactly, exactly, I was actually having a hard time figuring out why this didn't list an protocols for `NSMutableDictionary`... –  Jun 13 '13 at 05:14
  • its a great answer. Its worked fine. It might not work with ARC. but it will work with non ARC for sure. Thanks. – Shaheer Palolla Jun 13 '13 at 06:41
  • 1
    If you're trying to **get this to work with ARC** and getting a compile error, just add `__unsafe_unretained` right before `Protocol **p`l. – Jay Q. Jun 29 '16 at 03:11
3

There is exactly NSObject +conformsToProtocol; protocol conformance is declared as part of the @interface so it isn't specific to each instance. So e.g.

if( [[self class] conformsToProtocol:@protocol(UIScrollViewDelegate)])
    NSLog(@"I claim to conform to UIScrollViewDelegate");

No need to drop down to the C-level runtime methods at all, at least for the first limb of your question. There's nothing in NSObject for getting a list of supported protocols.

Tommy
  • 99,986
  • 12
  • 185
  • 204
2

You can try objc_copyProtocolList

I.e. you get the list of all protocols and then check if current object conforms to specific protocol by iterating the list.

Edit:

H2CO3 solution is really better one

Max
  • 16,679
  • 4
  • 44
  • 57