respondsToSelector Of Super
respondsToSelector is often used to determine whether an instance implements a method for safe calling.
But please don’t call the respondsToSelector method on super.
Sometimes we only want to call a method of the parent class, but we only know that although the parent class implements a certain protocol, it does not necessarily implement the method in the protocol.
[super message] has the following meaning:
When it encounters a method call, the compiler generates a call to one of the functions objc_msgSend, objc_msgSend_stret, objc_msgSendSuper, or objc_msgSendSuper_stret. Messages sent to an object’s superclass (using the super keyword) are sent using objc_msgSendSuper; other messages are sent using objc_msgSend. Methods that have data structures as return values are sent using objc_msgSendSuper_stret and objc_msgSend_stret.
But respondsToSelector is on NSObject, and the internal check logic does not have special processing for super, but only checks the actual calling instance.
1 | @protocol ProtocolA <NSObject> |
The correct way is to call the instancesRespondToSelector method on the parent class to check.
1 | + if ([A instancesRespondToSelector:@selector(funA)]) { // Good! |
There may be an idea whether it is possible to use [super class] to replace A?
Unfortunately this is another mistake, the correct way to do it is [self superclass]。
The reason is exactly the same as described earlier.
1 | (lldb) po [super class] |
1 | + if ([[self superclass] instancesRespondToSelector:@selector(funA)]) { // Good! |