问题
- iOS调用不存在的方法时,会发生crash,请问crash发生在什么阶段,这个问题该如何作答呢?
- 方法查找阶段?
- 消息转发阶段中?
- 消息转发阶段之后?
- 还是其它什么地方?
场景
我们知道,在oc中,当我们调用一个类中不存在的方法,会发生crash,错误信息大概是这样做:

预备
- 回想一下,oc是如何查找方法IMP的?
- 回想一下,oc消息转发机制是怎样的?
- 回想一下,如何测试、验证oc的消息转发机制?
- 可以参考:https://www.jianshu.com/p/fdd8f5225f0c
- 可以参考: https://www.jianshu.com/p/a36bfc976b8e
问题:
- 用心看这个crash信息,你想到什么?
打断点摸索一下
首先:
// 调用一个不存在的方法
[self performSelector:@selector(aaa:)];
第二:

第三:

第四:

问题:
如果在类中对这两个方法这样重写,猜猜看forwardInvocation会被调用么?想想为什么?
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if ([anInvocation selector] == @selector(jump)) {
Monkey *monkey = [[Monkey alloc] init];
[anInvocation invokeWithTarget:monkey];
}
[super forwardInvocation:anInvocation];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(jump)) {
return [NSMethodSignature signatureWithObjCTypes:"V@:@"];
}
return [super methodSignatureForSelector:aSelector];
}
第五:

forwardInvocation中的断点并没有走到,而是直接doesNotRecognizeSelector了。找个理由解释一下?
NSObject中doesNotRecognizeSelector的默认实现类似如下代码:
// Replaced by CF (throws an NSException)
+ (void)doesNotRecognizeSelector:(SEL)sel {
_objc_fatal("+[%s %s]: unrecognized selector sent to instance %p",
class_getName(self), sel_getName(sel), self);
}
那么是不是可以理解为:我在子类重写doesNotRecognizeSelector方法,不调用[super ]就不会crash了呢?

实际测试一下,依然会crash,想想为什么呢?欢迎吐槽抛抛出来的问题。
官方文档
- https://developer.apple.com/documentation/objectivec/nsobject/1571955-forwardinvocation
- https://developer.apple.com/documentation/objectivec/nsobject/1418855-forwardingtargetforselector?language=objc
- https://developer.apple.com/documentation/objectivec/nsobject/1571955-forwardinvocation?language=objc
- https://developer.apple.com/documentation/objectivec/nsobject/1418637-doesnotrecognizeselector?language=objc
网友评论