1.简单面试题
b 是Bird类的一个对象实例.
Bird类声明了一个对象方法 run,但是却没有实现该方法.
Bird类继承自Animal类,Animal类继承自NSObject类.
那么问题来了:
[b run];
运行结果如何?
2.如何回答&如何深问
2.1小白回答版
首先,编译时会有警告:
Method definition for 'run' not found
运行时会crash
2016-03-09 08:57:14.071 text[6568:1124581] -[Bird run]: unrecognized selector sent to instance 0x7fbd81f1e810 2016-03-09 08:57:14.083 text[6568:1124581] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Bird run]: unrecognized selector sent to instance 0x7fbd81f1e810
2.2深问第一步
为什么会crash呢?
2.3小菜回答版
程序在运行时,会到Bird类中找run相应的指针,拿到指针后去找实现代码,没有找到相应的代码,所以会崩溃.
2.4小鸟回答版
(http://www.cocoachina.com/ios/20141018/9960.html)
2.4.1 首先,编译器将代码[b run];转化为objc_msgSend(b, @selector (run));
2.4.2 在objc_msgSend函数中,首先通过b的isa指针找到b对应的类Bird。
在Bird类中先去cache中,通过SEL查找对应函数run(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度)
若cache中找到,那么跳转到对应的函数中执行.
2.4.3 若cache中未找到,则去methodList中查找,若找到,则执行.
2.4.4 若methodlist中未找到,则去Animal类中查找。若能找到,则将method加入到cache中,以方便下次查找,并通过run中的函数指针跳转到对应的函数中去执行.
2.4.5 若前面的步骤执行完之后仍未找到,则会去NSObject类中查找,仍查找不到,则会crash
2.5大鸟回答版
(http://www.cnblogs.com/oc-bowen/p/5253562.html)
由执行流程图中的各个函数可知,程序在crash之前还会执行一些函数,利用好这些函数,可以达到神奇的效果.
#import "Bird.h" #import <objc/runtime.h> @implementation Bird + (BOOL)resolveInstanceMethod:(SEL)sel{ if (sel == @selector(run)) { NSLog(@"want to run"); class_addMethod([self class], sel, (IMP)dynamicMethodIMP, "v@:"); return YES; } return [super resolveInstanceMethod:sel]; } void dynamicMethodIMP (id self, SEL _cmd) { NSLog(@"OK! Run!"); } @end
程序执行结果如下图所示:
程序没有crash,而且输出了OK! Run!
这意味着我们可以在程序crash之前做很多事情.
2.6大神回答版
大神的回答应该是全面细致,具有丰富的实战经验的,求各位大神赐教.