68

Is there a class method equivalent to -respondsToSelector:?

Something like +respondsToSelector:?

The reason I am asking is because by implementing -respondsToSelector: on a class level, I get a compiler warning: "found '-respondsToSelector:' instead of '+respondsToSelector:' in protocol(s)".

The code looks like this:

Class <SomeProtocol> someClass = [someInstance class];

if ([someClass respondsToSelector:@selector(someSelector:)]) {
    someVar = [someClass someSelector:someData];
}
firstresponder
  • 5,000
  • 8
  • 32
  • 38

5 Answers5

84

Update after seeing your edit:

A class object responds to respondsToSelector: just fine, as you're probably aware. In a test application, I can do both of the following without any compiler warnings:

NSLog(@"Responds to selector? %i", [MyObject respondsToSelector:@selector(respondsToSelector:)]);
NSLog(@"Responds to selector? %i", [[MyObject class] respondsToSelector:@selector(respondsToSelector:)]);

However, you've declared a protocol on your variable, so it assumes that the class object you're pointing to implements those methods. The simplest solution would be to cast someClass as an id for the purpose of calling respondsToSelector:. A somewhat cleaner solution would be to declare your own @protocol which declares +respondsToSelector:(SEL)selector, and then declare someClass as follows:

Class<SomeProtocol, ClassRespondingToSelector> someClass = ...

Finally, be sure to file a bug with Apple at http://bugreporter.apple.com. Include a simple test application so that it's very clear what you're doing. They welcome such bug reports, even if they've been submitted in the past, as it helps them prioritize the fixes.

Final note: this is probably happening because in theory, you could have chosen to implement a root object entirely separate from NSObject, and in that case, it wouldn't respond to -respondsToSelector:. -[NSObject respondsToSelector:] is actually declared in the NSObject protocol, not the class definition. The NSObject protocol is actually where most of what you know as NSObject actually lives. One could argue that +respondsToSelector: should also be in there, but as of now, it's not. And since you've provided a protocol list, and the method isn't in there, it gives you a warning to make sure you know what you're doing.

BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • I believe in this case he'd actually want to cast to Class, not id. – Joseph Lennox Jun 20 '14 at 15:55
  • 7
    This is either removed functionality or the answer is unclear. `Class` does not respond to `respondsToSelector:`. – RileyE Nov 12 '14 at 17:47
  • Try it. It's not in the header, but do `id classObject = [SomeClass class]; [classObject respondsToSelector:]` – BJ Homer Nov 12 '14 at 18:33
  • 1
    It actually works, as BJ Homer said, it's not in the header and therefore no auto completion through Xcode. That's what made me doubt. You need to fully type it. – wolfrevo Feb 28 '15 at 10:23
  • @RileyE agreed, me also faced this issue, can't find the equivalent `respondToSelector` in the `Class`. – Ratul Sharker Nov 20 '16 at 15:58
9

Well a class method is just a method of the class object, so you should be able to just do this

[MyClass respondsToSelector:@selector(...)]
newacct
  • 119,665
  • 29
  • 163
  • 224
  • I get a compiler warning: "found '-respondsToSelector:' instead of '+respondsToSelector:' in protocol(s)". How do I get rid of this compiler warning? – firstresponder Jul 16 '09 at 05:09
  • I can get rid of the compiler warning by dropping the protocol type qualifier ''. Why is that? Is that syntax not correct? – firstresponder Jul 16 '09 at 05:14
  • 3
    firstresponder: Objective-C is a dynamic language. If you send a message to a `Class` or `id` without qualifying that type further (with a protocol), the compiler assumes that you are doing some kind of responds-to-selector or is-kind-of-class check yourself. However, if you do specify a protocol or (for instances) a specific class, it gets helpful and performs the check for you. Since the protocol you've declared the variable with doesn't have a `+respondsToSelector:` declaration, the compiler raises a warning. – Peter Hosey Jul 16 '09 at 09:00
  • I've noticed the casting with protocol behavior is different in Xcode 9. It accepts the casting there but not in 8 and lower. – Will Larche Nov 14 '17 at 15:51
5

You can use the following instancesRespondToSelector: since iOS 2.0, so where with an instance of a class you can do;

[myInstance respondsToSelector: @selector(...)];

With a class you can use

[myClass instanceRespondsToSelector: @selector(...)];
// or
[[myInstance class] instanceRespondsToSelector: @selector(...)];

Which will behave like +(BOOL) respondsToSelector

Hugo Scott-Slade
  • 896
  • 9
  • 16
  • 6
    This would answer if instances of the class would respond to the selector, not if the class itself would respond to the selector statically. – Jonny Apr 11 '13 at 06:48
2

What I think you were asking is: Can you ask a class if it responds to +someMethod or not? In other words, thinking of the Cocoa Touch APIs, you would want:

[ [ UIView class ] respondsToSelector: @selector( buttonWithType: ) ] -> NO
[ [ UIButton class ] respondsToSelector: @selector( buttonWithType: ) ] -> YES

But what I wrote above doesn't work as desired. respondsToSelector: is only about instance methods. (Thus both calls will return NO.) Within the Cocoa APIs there is no equivalent to respondsToSelector: for a class.

You can, however, call class_getClassMethod. If the result is non-NULL, the class method you are asking about is present and you can call it.

escouten
  • 2,883
  • 2
  • 21
  • 23
  • 8
    This is false. `respondsToSelector:` works just fine on `Class` objects to report the existence of class methods. – Dave DeLong Sep 16 '10 at 03:26
  • I up-vote this dude, because he was actually correct with his `class_getClassMethod` approach. If I have had enough patience to read the entire thread I wouldn't have to reinvent the same solution. – bioffe Sep 16 '10 at 21:59
  • 1
    I down-vote this, because class methods *are* instance methods on the class object. – user102008 Aug 01 '11 at 22:16
  • 4
    -1 You're describing the behaviour of `+instancesRespondToSelector:`. `-respondsToSelector:` on a class object works entirely differently. –  Aug 30 '11 at 01:18
0

In Objective C, classes are also objects so you can send the object messages. In particular, you can ask -respondsToSelector: of a class. You can't send class level methods to non-class objects though.

Ken
  • 30,811
  • 34
  • 116
  • 155