对Runtime有了解吗,Runtime的方法查找过程是什么样的?有哪些实际应用?
runtime是OC动态语言的运行时机制,OC的方法调用最后都转成了runtime的objc_msgSend函数。
Runtime的消息传递
消息传递
1.通过哈希算法,先从方法缓存中查找,如果命中,调用方法结束流程
2.如果缓存中没有,则去当前类的方法列表中查找,如果命中,调用方法,加入当前方法缓存中,结束流程
3.如果当前类没有对应方法,则去逐级父类方法列表中查找,如果命中,调用方法,加入当前方法缓存中,结束流程
4.如果方法都不存在,进入方法动态解析,转入消息转发流程。
注:对于已经排序好的方法列表,采用二分查算法查找对应的执行函数,对应没有排序的列表,采用一般遍历方法查找对应执行函数。
消息转发流程
转发流程
1.调用动态解析方法resolveClassMethod:(SEL)sel,如果动态添加方法(调用class_addMethod函数)并返回YES,则结束流程
2.如果上一步没有实现动态添加方法,无论返回Yes还是No,都会调用消息接受者重定向forwardingTargetForSelector方法,如果返回重定向接受者,则当前流程结束
3.如果返回上一步nil,则会调用methodSignatureForSelector获取函数的参数和返回值类型,同时调用forwardInvocation消息通知当前对象。
4.如果上一步返回nil,消息无法处理,App crash。
继承关系
继承关系
- 实例对象(isntance)的isa指针指向类对象(class),类对象的存放实例方法(-方法)
- 类对象(class)的isa指针指向其元类对象(meta), 元类对象存放类方法(+方法)
- 根类对象(root class)的isa指针指向根元类对象(root meta),superclass指针指向nil.
- 根元类对象(root meta)的isa指针指向自己,superclass指针根类对象(root class)
由此可知, 实例方法(-方法)查找是沿着其superclass指针逐级父类查找,终于根类对象(root class)。而类方法(+方法)查找是沿着其superclass指针逐级父类(meta)查找,终于根类对象(root class),如果根类对象存在同名实例方法,则会调用同名实例方法
Runtime实际运用
- 给NSTimer定时器声明一个中间类Proxy(消息转发)
- 通过rumtime动态获取类的所有属性(json转model、可归档类对属性的归档及解归档操作)
- 反射机制(NSClassFromString, CTMediator原理)
- 交换系统方法(比如交换viewController生命周期方法,从而进行统一埋点等操作)
- 给分类添加属性(通过关联对象,实现getter, setter方法)