Recently, I have been studying the runtime in Objective-C.
I created a class with the name TO:
@interface TO : NSObject
@end
#import "TO.h"
@implementation TO
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSLog(@"%@ sel: %@", NSStringFromSelector(_cmd), NSStringFromSelector(aSelector));
return nil;
}
- (BOOL)respondsToSelector:(SEL)aSelector {
NSLog(@"%@ sel: %@", NSStringFromSelector(_cmd), NSStringFromSelector(aSelector));
return NO;
}
+ (BOOL)resolveClassMethod:(SEL)sel {
NSLog(@"%@ sel: %@", NSStringFromSelector(_cmd), NSStringFromSelector(sel));
return NO;
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"%@ sel: %@", NSStringFromSelector(_cmd), NSStringFromSelector(sel));
return NO;
}
+ (IMP)instanceMethodForSelector:(SEL)aSelector {
NSLog(@"%@ sel: %@", NSStringFromSelector(_cmd), NSStringFromSelector(aSelector));
return nil;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"%@", NSStringFromSelector(_cmd));
}
@end
Then I call the irrevocable selector somewhere:
TO *to = [TO new];
id res = [(NSString *)to uppercaseString];
Subsequently, I got the following output:
2015-12-22 22:27:04.319 OCDemo[81920:7728539] resolveInstanceMethod: sel: uppercaseString
2015-12-22 22:27:04.320 OCDemo[81920:7728539] forwardingTargetForSelector: sel: uppercaseString
2015-12-22 22:27:04.320 OCDemo[81920:7728539] resolveInstanceMethod: sel: uppercaseString
2015-12-22 22:27:04.320 OCDemo[81920:7728539] -[TO uppercaseString]: unrecognized selector sent to instance 0x7fdd3ad120a0
2015-12-22 22:27:04.322 OCDemo[81920:7728539] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TO uppercaseString]: unrecognized selector sent to instance 0x7fdd3ad120a0'
As we see, it resolveInstanceMethod:is called twice.
However, if I first call -[description]:
TO *to = [TO new];
[to description];
id res = [(NSString *)to uppercaseString];
Then the output will be:
2015-12-22 22:58:50.458 OCDemo[82137:7813436] resolveInstanceMethod: sel: uppercaseString
2015-12-22 22:58:50.459 OCDemo[82137:7813436] forwardingTargetForSelector: sel: uppercaseString
2015-12-22 22:58:50.459 OCDemo[82137:7813436] -[TO uppercaseString]: unrecognized selector sent to instance 0x7f9bcad59960
2015-12-22 22:58:50.461 OCDemo[82137:7813436] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TO uppercaseString]: unrecognized selector sent to instance 0x7f9bcad59960'
This time it resolveInstanceMethod:is called only once.
Can someone explain this?