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)


执行流程.png


由执行流程图中的各个函数可知,程序在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

程序执行结果如下图所示:


程序执行结果.png


程序没有crash,而且输出了OK! Run!
这意味着我们可以在程序crash之前做很多事情.

2.6大神回答版

大神的回答应该是全面细致,具有丰富的实战经验的,求各位大神赐教.

你可能感兴趣的内容
IOS 简洁输入框的实现 收藏,3448 浏览
iOS开发-plist文件增删改查 收藏,2910 浏览
减小iOS应用程序的大小 收藏,3022 浏览
0条评论

dexcoder

这家伙太懒了 <( ̄ ﹌  ̄)>
Owner