1. 什么是runtime
runtime就是一个C语言库,它使得OC语言成为一种动态语言,将很多编译时进行的事情推迟到runtime中进行。动态语言的本质就是在运行时才根据方法的名称去寻找到方法的具体执行。runtime主要做的事情归纳起来就两件。
(1)封装:runtime将对象转化为C语言的结构体,将方法转化为C语言的函数。
(2)寻找方法的具体执行
2. isa指针
对象的isa指针指向本身的类,类的isa指针指向父类,父类的isa指针最终指向元类(meta-class),元类的isa指针指向NSObject,NSObject的isa指针指向自身。
作用:对象在调用一个方法的时候,其实就是向这个对象发送一条消息,然后isa指针会告诉系统如何按照自己的指向顺序去找到这个方法,找到了就会执行这个方法。没找到则会走消息转发的机制,最终抛出异常。
2.SEL
SEL是一个指针,编译时系统会根据方法名hash化生成一个唯一的整形标志(所以同一个类中不能有两个重名的方法),这个标志就是SEL,SEL指向的是方法。
3.IMP
IMP是一个指针,它指向的是对应的方法实现。
4.Method
Method是一个结构体,里面包含了一个SEL和一个IMP
5.消息发送
执行[receiver message]的过程:
(1)通过isa指针找到对象的类,首先在这个类的method中寻找对应的SEL
(2)没找到则继续去父类中寻找
(3)找到之后也就找到了对应的IMP,执行相应的方法
(4)没找到会一直往上找到NSObject,还没找到后续将会走消息转发流程
6.消息转发
备注:如果想要在方法抛出异常前做点什么,就需要在这个过程中加入自己的方法实现。
7.runtime应用
(1)获取属性列表
(2)获取成员变量列表
(3)获取方法列表
(4)获取协议列表
(5)方法交换method-swizzling
(6)添加方法
(7)调用私有方法
(8)为分类添加属性
比如替换系统的加载图片的方法imageNamed,在自定义的方法中实现一个逻辑:当传入图片为空的时候使用默认填充图片。
获取系统的私有方法,比如我们知道系统的导航栏控制器界面的左侧,已经支持手势右滑返回的功能,加入我们现在需要做全屏右滑返回的功能。其实我们就可以通过runtime观察到系统实现该功能调用的方法名。拿到该方法名后,我们就可以添加全屏返回手势,很方便的实现全屏手势返回。
- (void) fullScreenPanBack { // 获取系统自带滑动手势的target对象 id target = self.interactivePopGestureRecognizer.delegate; // 创建全屏滑动手势,调用系统自带滑动手势的target的action方法 UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:target action:NSSelectorFromString(@"handleNavigationTransition:")]; [pan setEdges:UIRectEdgeLeft]; // 设置手势代理,拦截手势触发 pan.delegate = self; // 给导航控制器的view添加全屏滑动手势 [self.view addGestureRecognizer:pan]; // 禁止使用系统自带的滑动手势 self.interactivePopGestureRecognizer.enabled = NO; }
8.runtime 相关的面试题总结