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! |