runtime的三种调用方式
1.runtime api
2.NSObject api
3.OC上层方法 @selector
OC对象
OC对象的本质是一个结构体。
由ivars,imp组成。
方法
方法的本质是发送消息
类似于
void runIMP(id self, SEL _cmd) {
}
我们常见的sel,是一个方法编号。imp是函数实现的指针,通过SEL找到imp,调用函数。
那么问题来,sel是怎么找到imp的?
sel下层通讯
@selector(myFunc)
经过编译将处理为
objc_msgSend(myObjc, sel_registerName("myFunc"));
以上为对象方法,还有
类方法:
objc_msgSend(objc_getClass("MyClass"), sel_registerName("myFunc"))
父类发送消息:(对象方法)
struct objc_super mySuper;
mySuper.receiver = s
mySuper.super_class = class_getSuperclass(s.class)
objc_msgSendSuper(&mySuper, @selector(myFunc))
父类发送消息:(类方法)
struct objc_super myClassSuper;
myClassSuper.receiver = s.class
myClassSuper.super_class = class_getSuperclass(object_getClass());
objc_msgSendSuper(&myClassSuper, sel_registerName("myFunc"));
类方法
对象在类里是一个实例,类在元类里也是一个实例。
所以类方法在元类里,是以对象方法的姿态存在的。
objc_msgSend的两种方式
1.快速查找
在objc_class里
superclass为父类
bits为各种数据
而cache就是一个哈希表。用来存储方法的sel和imp。如果没找到,则走慢速查找。
image.png
2.慢速查找
动态方法解析
当在运行时实例方法并未实现的时候,动态方法解析就可以闪亮登场了。
image.png上图可以看到,动态解析只会执行一次。
image.png实例方法执行
_class_resolveInstanceMethod(cls, sel, inst);
+ (BOOL)resolveInstanceMethod:(SEL)sel{
return [super resolveInstanceMethod:sel];
}
类方法执行
_class_resolveInstanceMethod(cls, sel, inst);
+ (BOOL)resolveClassMethod:(SEL)sel{
return [super resolveClassMethod:sel];
}
在实践中,我们会发现resolveInstanceMethod被执行了两次,这是为什么呢?
isa走位流程.png
这时候首先需要搞明白isa的走向。
实例方法 -> 元类 -> 根元类 -> NSObject的实例方法
可知,实例方法调用了一次,NSObject调用了一次。
第一次拯救崩溃
众所周知当调用的方法未实现时,程序会崩溃。
而在方法动态解析时,runtime提供了一次拯救崩溃的机会。
#include <objc/runtime.h>
@interface Person : NSObject
- (void)doSomething;
@end
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(doSomething)) {
//动态方法解析
SEL otherSel = @selector(otherThing);
Method otherMethod = class_getInstanceMethod(self, otherSel);
IMP otherImp = method_getImplementation(otherMethod);
const char *type = method_getTypeEncoding(otherMethod);
return class_addMethod(self, otherSel, otherImp, type);
}
return [super resolveInstanceMethod:sel];
}
类方法同理,为元类动态增加实例方法。
第二次拯救崩溃,方法转发流程
当第一次resolveInstanceMethod执行后,如果消息依然无法进行处理,将会有第二次拯救崩溃的机会,来到消息转发流程。
消息转发流程.png
网友评论