runtime-对象和方法
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。
- OC对象的本质 -> 结构体
oc文件->.cpp文件:
clang -rewrite-objc main.m -o main.cpp
- 完整命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.c++
- 方法的本质 -> 消息发送
objc:
- (void)run { }
对应底层C:
void run(id self, SEL _cmd) { }
-
方法: 对象方法和类方法.
-
runtime的调用方式:三种:
- runtime api: class_get...
- NSObject api: isKindOf isMemberOf
- oc上层方法: @selector
- 对象方法的调用:
Object *obj = [Object new];
[obj run];
- 方法调用的底层编译
- 方法的本质: 消息: 消息接受者 消息编号 ...参数(消息体)
objc_msgSend(obj, sel_registerName("run"));
- 类方法编译底层
id cls = [ObjectClass class];
void *pointA = &cls;
[(__bridge id)pointA walk];
===
objc_msgSend(objc_getClass("ObjectClass"), sel_registerName("walk"));
- 向父类发消息(对象方法):
struct objc_super mySuper;
mySuper.receiver = obj;
mySuper.super_class = class_getSuperclass([obj class);
objc_msgSendSuper(&mySuper, @selector(run));
- 向父类发消息(类方法):
struct objc_super myClassSuper;
myClassSuper.receiver = [obj class];
myClassSuper.super_class = class_getSuperClass(object_getClass([obj class])); // 元类
objc_msgSendSuper(&myClassSuper, sel_registerName("walk"));
-
对象方法存在类中
-
类方法存在元类中
-
类方法在元类中,以什么样的姿态存在?
:以实例方法存在. -
对象在类中是以实例存在.
-
类在元类中也是以实例形式存在.
-
objc_msgSend
两种方式:
- 快速 by汇编 缓存找 cache_t imp 哈希表
- 慢速 c, c++一起完成,找到存缓存
否则 经过复杂的过程
为什么使用汇编写?
- c 写一个函数,不可能保留未知的参数,跳转到任意的指针.
- 块,c还要向下编译
- 汇编可以保存,by 寄存器 x0 x31
- 源码分析流程
- 汇编部分
- c,c++部分
具体查看 opensource.apple.com -> objc4
分析源码的文件是objc4中arm64相关的.s汇编文件,然后汇编中有__class_lookupMethodAndLoadCache3一个宏调用,要在工程中使用_class_lookupMethodAndLoadCache3来查找,因为在.mm文件里面.
大概的过程:
- 消息发送调用后,通过汇编,从汇编的缓存中查找
- 如果找到,那么就直接调用,否则查找方法实现的函数指针,找到实现函数指针,就返回函数指针
- 如果在缓存中找不到,也找不到函数指针,那么通过c、c++函数去找,先是自己的类中找,然后递归从父类中查找。
- 如果找到,那么就fill cache并且返回这个函数指针。找不到的话,那么就要开始走动态解析了。
-- Warning:
在c、c++的查找过程中,会再次判断一下缓存中是否有函数实现,尽管汇编过程中已经判断过缓存。这个原因是:oc语言的动态性,并发,有可能使缓存中有值了。
- 动态方法解析.
类的方法解析:(动态方法解析的函数名一样,只是前缀是-,而不是+)
+ (BOOL)resolveInstanceMethod:(SEL)sel {
return [super resolveinstanceMethod: sel];
}
+ (BOOL)resolveClassMethod:(SEL)sel {
return [super resolveClassMethod: sel];
}
发布于2024-01-30 03:58:16
浏览量53·
暂无评论,快来发表第一条评论吧