美文网首页
OC总结篇 - OC对象及方法

OC总结篇 - OC对象及方法

作者: 亲爱的大倩倩 | 来源:发表于2019-10-09 15:02 被阅读0次
1.OC对象 = 结构体

id对象 = objc_object结构体
继承
类对象 = objc_class结构体

objc_object结构体如下

1. isa指针
       isa_t 是共用体,由32或64个0或者1的数字组成
       指针型:isa的值全部代表所指向的class地址
       非指针型:isa的值部分代表class地址, 节省内存
2. 关于isa操作相关方法, 来获取它的isa指向
3. 弱引用相关方法, 标记对象是否有过弱引用
4. 关联对象相关方法
5. 内存管理相关方法, retain, release, AutoReleasePool

objc_class结构体在拥有上面的基础上,新增如下

1. superClass
2. cache:里面存储方法的SEL和IMP,SEL和IMP组成了一个哈希表
        是由bucket_t组成的数组,里面是keyValue结构:SEL-IMP,当有了key,可以通过哈希查找算法,来定位当前key对应的bucket_t位于数组哪个位置,找到后再提取里面的IMP具体实现
        特点1:是可增量扩展的哈希表结构,当存储量结构增大时,会自动扩展内存空间来支持更多缓存
        特点2:把调用频次高的方法放到缓存中,它是可以快速查找方法的执行函数,当我们调用方法时,如果有cache,就不用去方法列表中查找,可以提高消息传递的速度
3. bits:存储类的变量,属性和方法等
        class_ro_t代表类相关的只读信息,创建类时添加的成员变量和方法列表,后续无法修改
        class_rw_t代表类相关的读写信息,可读可写,例如可以随时创建分类

cache



bits


2.类对象和元类对象

都是objc_class结构,都有isa指针
区别
类: 存储实例对象和实例方法
元类: 是种虚拟的类, 存储类对象和类方法
根元类: 存储元类方法

isa指向
1. 实例方法 - 类对象    当我们调用实例方法,是通过isa指针去类对象中查找
2. 类方法 - 元类对象    当我们调用类方法,是通过isa指针去元类对象中查找
3. 元类方法(包括根元类自身) - 根元类对象    当我们调用元类方法,是通过isa指针去根元类对象中查找
superclass指向
1. 类方法 - 父类对象 - NSObject - nil
2. 元类方法 - 元类父类 - 根元类父类 - NSObject - nil
 
?????当我们调用类方法,在元类对象方法列表中查找不到时,就会找到NSObject中同名的实例方法
3.OC方法本质 = 利用Runtime的 objc_msgSend(消息接收者,方法编号SEL) 方法发送消息

[self class] = objc_msgSend(self,@selector(class))

4.消息传递流程(参考isa和superClass指向图,注意不是按照isa层层传递,isa只找一次)

1. 快速法: 在缓存中使用汇编,哈希查找IMP
根据给定的方法选择器SEL,经过哈希函数算法算出的值,就是对应的bucket_t中的索引位置,然后找到bucket_t中具体的方法实现IMP

2. 慢速法: 缓存找不到,则进入消息传递流程
根据当前实例的isa指针去查找当前类对象的方法列表,已排序好的列表用二分查找,没有排序的列表,采用一般遍历,若当前类对象中没有,根据当前类对象superclass指针递归去父类方法列表中去查找IMP,在父类中也是先查找缓存,再查找父类,找到了,回去缓存中存到哈希表中,便于下次的快速查找
若查到NSObject都没有,则进入消息转发阶段

#注意不是按照isa层层传递,isa只找一次
1. 实例方法的调用
   通过isa找到类对象中去遍历方法列表
   若找不到,就会沿着superclass去递归遍历父类对象方法列表
   如果查到NSObject还找不到就会进入消息转发流程

2. 类方法的调用
   通过类对象的isa找到元类对象
   若找不到,会沿着superclass去递归遍历父类对象的方法列表
   若查到根元类还找不到,就会去NSObject中查找
   如果查到NSObject还找不到就会进入消息转发流程
5.消息转发流程
1. 方法决议 
   resolveInstanceMethod告诉系统要不要解决这个方法实现,若没有进入2
  # 可以在这里动态添加SEL方法,也可以做别的比如写入日志,然后重新执行方法查找(去递归查找)

2. 寻找响应该消息的对象
   forwardingTargetForSelector尝试找到一个能响应该消息的对象,如果找到了,则将消息发给它,会重新从该对象开始执行查找方法实现的流程,找到了也同样会在 object 的类对象的 _buckets 里缓存起来
    如果没有,执行3
  # 可以收集crash,防止崩溃

3. 尝试获得方法签名
   methodSignatureForSelector尝试获得一个方法签名
   这是最后一次机会,对这个实例方法的返回值类型和参数个数参数类型的封装,叫做方法签名

4. 如果有方法签名,包装成 Invocation 传入,交给forwardInvocation去处理
   如果消息签名为nil.则调用doesNotRecognizeSelector抛出异常
# 1.系统调用堆栈,存到沙盒里发给服务器,类似友盟收集崩溃,2.切面编程,埋点
  

相关文章

网友评论

      本文标题:OC总结篇 - OC对象及方法

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