美文网首页
runtime 运行时 使用

runtime 运行时 使用

作者: 爱喝农药de清凉 | 来源:发表于2018-03-23 10:39 被阅读18次

一、消息机制
头文件 :<objc/message.h>
设置:【build Setting】 搜 @“msg” -> Enable strict checking of objc_msgSend calls 设置 NO


image.png

例 : 创建一个类,调用方法
OC: Person * p = [[Person alloc] init];
调用方法一: [p miao];
调用方法二: [p performSelector:@selector(miao)];

msg: Person * p = [[Person alloc] init];
objc_msgSend(p,@selector(miao));
so: Person * p = [[Person alloc] init] 可以写成
Person * p = objc_msgSend(Person.class, @selector(alloc));
p = objc_msgSend(p, @selector(init));
完全C语言写法 :
Person * p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));
p = objc_msgSend(p, @selector(init));
其中 Person.class -> objc_getClass("Person")
@selector(alloc) -> sel_registerName("alloc")

补充: 编译器会根据情况在 objc_msgSend,objc_msgSend_stret,objc_msgSendSuper,objc_msgSendSuper_stret 或 objc_msgSend_fpret 五个方法中选择一个来调用。如果消息是传递给超类,那么会调用 objc_msgSendSuper 方法,如果消息返回值是数据结构,就会调用 objc_msgSendSuper_stret 方法,如果返回值是浮点数,则调用 objc_msgSend_fpret 方法。

image.png

当调用 [super class] 时,会转换成 objc_msgSendSuper 函数:

第一步先构造 objc_super 结构体,结构体第一个成员就是 self。第二个成员是 (id)class_getSuperclass(objc_getClass(“Son”)).
第二步是去 Father 这个类里去找 - (Class)class,没有,然后去 NSObject 类去找,找到了。最后内部是使用 objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和 [self class] 调用相同了,所以两个输出结果都是 Son。

二、runtime 运用
头文件: <objc/runtime.h> 注: <objc/message.h> 包含 <objc/runtime.h>,只用 <objc/message.h> 即可

1、获取某个类属性列表
//属性个数 其中.m 中的属性 也可以拿到
unsigned int count = 0;
// copy new creat 代表毁在 堆区 (Malloc) 开辟空间
// Ivar 成员属性
Ivar * list = class_copyIvarList(Person.class, &count);
for (int i = 0; i < count ; i++) {
Ivar ivar = list[i];
//通过 Ivar 拿到属性名称
const char * name = ivar_getName(ivar);
NSString * key = [NSString stringWithUTF8String:name];
}
//防止内存溢出
free(list);

2、给一个类动态添加新方法
方法: class_addMethod(<#Class _Nullable __unsafe_unretained cls#>, <#SEL _Nonnull name#>, <#IMP _Nonnull imp#>, <#const char * _Nullable types#>)
参数说明:
Class: 你要添加新方法的那个类
SEL name : 要添加的方法
IMP : 指向实现方法的指针 就是要添加的方法的实现部分
types: 要添加的方法的返回值和参数 集体参照官方文档

在OC中找不到对相应的实现方法时 有补救机制 即 会先调用动态决议方法 该方法解决不了问题 再调用重定向方法 都解决不了问题是 crash
动态决议方法:


image.png

重定向方法:


image.png image.png

补充:为什么 能在 方法中调到 self ?只因为他是关键字?
说明:
OC: void mou(id self , SEL _cmd) ,其中 self,_cmd.默认隐藏
C: objc_msgSend(object_getClass("Person"), sel_registerName("mou"))
其中:self 对应 Person _cmd 对应 sel_registerName("mou")

3.把一个对象与另外一个对象进行关联
objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略


image.png

关键字是一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字。

关联策略表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。这种关联策略是通过使用预先定义好的常量来表示的。


image.png
image.png

断开连接:
断开关联是使用objc_setAssociatedObject函数,传入nil值即可。
使用函数objc_removeAssociatedObjects可以断开所有关联

相关文章

网友评论

      本文标题:runtime 运行时 使用

      本文链接:https://www.haomeiwen.com/subject/pxsaqftx.html