Is there any introspection method to get all adopted protocols for a class in Objective-C?
Asked Answered
C

3

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?

Codd answered 12/6, 2013 at 16:47 Comment(2)
What exactly are you trying to accomplish with this?Cavort
@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?Gan
J
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);
Jodee answered 12/6, 2013 at 19:30 Comment(4)
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.Kristopherkristos
@MartinR Exactly, exactly, I was actually having a hard time figuring out why this didn't list an protocols for NSMutableDictionary...Jodee
its a great answer. Its worked fine. It might not work with ARC. but it will work with non ARC for sure. Thanks.Codd
If you're trying to get this to work with ARC and getting a compile error, just add __unsafe_unretained right before Protocol **pl.Gopherwood
G
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.

Gan answered 12/6, 2013 at 20:42 Comment(0)
A
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

Arc answered 12/6, 2013 at 16:53 Comment(3)
Or class_copyProtocolList().Kristopherkristos
How to practically use it?Codd
I don't think objc_copyProtocolList() is the right option here -- that gets all protocols that exist, anywhere. class_copyProtocolList() tells you which protocols a class actually declares conformance to.Windsucking

© 2022 - 2024 — McMap. All rights reserved.