iOS Runtime

runtime数据结构

  1. id = objc_object
    isa_t
    关于isa草错相关
    弱引用相关
    关联对象相关
    内存管理相关

2.Class = objc_class 继承自objc_Object,是一个列独享
Class superClass
cache_t cache(方法缓存)
class_data_bits_t (类的变量,属性,和方法)

isa指针

共用体isa_t(64位或者32位置,0或者1的数字)
指针型isa,64位的0或者1,isa的值代表Class的地址
非指型isa,是指的是部分的值代表Class的地址

isa方向

  • id对象,指向类对象
  • 类对象,指向元类对象
    如果我没调用一个方法,如果是实例对象是通过它的isa指针去他的类对象中查找,如果是类对象则是通过isa指针去他的元类对象中去查找。

cache_t

用于快速查找方法执行的函数
是可增量扩展的哈希表结构
是计算机局部性原理的最佳应用(把调用频次更高的放在缓存池中)
是有bucket_t组成,里面有key(对应SEL)和IMP(无类型的函数指针)

class_data_bits_t

是对class_rw_t的封装。
class_rw_t代表了类型管的读写信息(给累的分类、协议等),对class_ro_t 的封装,代表累的相关的只读信息。

  • class_rw_t的组成
    class_ro_t
    protocols
    properties
    methods

  • class_ro_t的数据结构(类原始定义,不是后来添加的)
    name(可以反射获得)
    ivars(成员变量)
    properties(属性)
    methodLists

  • methods
    函数的四要素
    名称 - SEL name
    返回值 - const char*types
    参数 - …
    函数体 - IMP imp

  • Tpye Encodings 机制,和const char*types相关
    不可变的字符指针
    返回值 参数1 参数2 … 参数n

  • (void)aMethod <=> V@:
    V 返回值void
    @ 对象 id
    : SEL

类对象和元类对象

类对象和元类什么关系和区别是什么?

  • 类对象存储实例方法列表等信息
  • 元类对象存储类方法列表等信息
    实例对象可以通过isa指针找到他的类对象,访问实例方法列表等信息。
    类对象可以通过isa指针访问元类对象找到类方法列表等信息。
    类对象和元类的对象都是继承自objc_class数据结构,所以都是有isa指针。
    元类对象的isa指针都指向根元类对象,根元类对象的isa指针指向自己。
    而根元类对象的父类指针指向根类对象,当元类对象没有这个方法的时候会去根类对象中找实例方法有没有同名的方法。

总结:调用的实例方法,会根据isa指针去找到类对象,在类对象中去遍历方法实现,没有查找的话顺着supperclass这真去找。
调用的类方法,会根据isa指针去找到元类对象,在元类对象中去遍历方法实现,没有查找的话顺着supperclass这真去找一直找到跟元类对象。

消息传递

supper是编译关键字,super的数据结构指的是当前对象。所以supper的接收者是当前对象。

  • 缓存查找的流程和步骤
    给定值SEL,目标是对应bucket_t的IMP,是哈希查找,通过key和哈希操作找到索引的位置。
    哈希查找是为了效率,找到bucket_t之后找到IMP

  • 当前类中查找
    已经排序好的,用二分算法查找对相应的执行函数
    没有排序好的,用一半遍历算法查找对相应的执行函数

  • 父类逐级查找过程

通过当前类结构的supperClass转移父类,然后判断父类是否为空,如果父类是nil,结束父类查找。如果父类不是nil,就去父类的方法缓存中找,然后找父类的方法列表。

  • 总结
    消息传递机制,缓存-> 类方法列表 -> 父类方法逐级列表中找 -> 消息转发

消息转发

resolveInstanceMethod: 是个类方法,告诉系统要不要实现,返回是Yes的话消息已经处理,返回No的话,制定一个转发目标。

Method-Swiziing

什么是Method-Swizzling

交换前
selector -> IMP1
selector -> iMP2

交换后
selector -> IMP2
selector -> iMP1

步骤:
导入runtime的头文件
在Load方法之
class_getInstanceMethod 获取方法的结构体
method_exchangeImplementation

实际应用

动态添加方法

performSelector:

如何为一个类动态的添加一个方法

动态方法解析

@dynamic,get和set方法指的是在运行时添加

动态运行时语言将函数决议推迟的运行时决定,实际是在运行时添加get 和 getshier
编译时语言在编译期进行函数决议

RunTime实战

[obj fool] 和objc_msgSend()函数之间有什么关系?
runtime如何通过Selector找到对性的IMP地址的?
能否向编译后的类中增加实例变量?

https://blog.csdn.net/ochenmengo/article/details/104923110?spm=1001.2014.3001.5501

你可能感兴趣的:(iOS Runtime)