美文网首页
iOS runtime详细内容

iOS runtime详细内容

作者: XieHenry | 来源:发表于2021-04-14 22:52 被阅读0次
runtime的主要数据结构.png

一. objc_object结构体 objc_class结构体

1.1 objc_object结构体
image.png image1.png
  • isa指针分为 指针型isa非指针型isa
image.png
1.2 objc_class结构体
结构体主要内容:
struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() { 
        return bits.data();
    }
    ......
}
image.png
1.3 cache_t结构体
struct cache_t {
    struct bucket_t *_buckets;//可以理解为一个数组
    mask_t _mask;
    mask_t _occupied;
    ......
}
方法缓存的数据结构.png 通过哈希查找.png image.png

cache_t的特点:
1.用于快速查找方法执行函数
2.是可增量扩展哈希表结构(增量拓展:结构的量增大,内存也会增大)
3.是局部性原理的最佳应用(局部性原理:调用次数较高的方法)

1.4 class_data_bits_t结构体

class_data_bits_t包含class_rw_t,class_rw_t内包含

struct class_rw_t {
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;
    ......
}
struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};
image.png
  • 一个类定义的变量 方法 属性都在class_data_bits_t这个成员结构内
image.png

protocols(协议) properties(属性) methods(方法) 是一个二维数组,还包括一些分类等

image.png

name 类名
ivars 声明,定义的成员变量
properties 属性
protocols 协议
methods 方法
他们是一个一维数组

image.png image.png

二.类对象 元类对象

类对象 存储实例方法列表等信息
元类对象 存储类方法列表等信息

image.png

问题1:类对象和元类对象之间有什么区别和联系?

实例对象通过isa指针找到类对象
类对象当中存储方法列表等信息
类对象通过isa指针找到元类对象、从而可以访问类方法列表等相关信息
类对象和元类对象都是objc_class数据结构,因为继承objc_object。所以他们才有isa指针,进而可以实现实例对象通过isa指针找到类对象,进而可以访问实例方法列表等信息。类对象通过isa指针找到元类对象、从而可以访问类方法列表的相关信息。

问题2:如果我们调用的类方法,没有对应的实现。但是有同名的实例方法,会不会发生崩溃,会不会产生实际的调用?

由于根元类对象的superclass指针,指向了根类对象,当我们在元类对象当中查找类方法列表查不到的时候。会顺着指针去实例方法列表查找。如果有同名方法,就会调用同名方法的实例方法调用。

问题3:实例方法的传递过程?

系统根据当前的isa指针。找到它的类对象,在它的类对象当中查找方法列表。没有查找到的话,就会根据superclass查找父类的类对象的方法列表。然后根类对象的方法列表,如果还没有,就进入消息转发流程。

问题4:类方法的传递过程?

通过类对象的isa指针,找到元类对象。在它的元类对象当中查找方法列表。没有查找到的话,就会根据superclass查找父类的元类对象的方法列表。然后顺次遍历方法列表,直到根元类对象,再到根类对象。然后根类对象的方法列表,如果还没有,就进入消息转发流程。

问题4:类对象 元类对象isa指向问题。

元类对象的isa指针 指向 根元类对象
根元类对象isa指针 指向 根元类对象
根元类对象的superclass指针指向根类对象

问题5:打印结果

image.png

结果都是Phone。因为接收者都是当前对象。


image.png

问题6:消息传递的机制?
首先通过 哈希查找 查找缓存,缓存没命中,查当前类的方法列表是否命中(对于已排序好的列表,采用二分查找,对于没有排序的列表,采用一般遍历查找方法)。如果仍然没命中,逐级父类方法列表是否命中(父类查找是先通过superclass指针查找父类,遍历每一个父类,对于每一个父类,又通过缓存查找和当前类方法列表查找)。如果都没有命中,进入消息转发流程。

image.png

问题7:[obj foo]和objc_msgSend()函数之间有什么关系?
编译之后,会在内部变成objc_msgSend()函数调用。

问题8:消息转发流程3个步骤
1.resolvelnstanceMethod(告诉系统是否要解决当前的方法实现)
2.forwardingTargetForSelector:(告诉系统这个实例方法的调用应该由哪个对象来处理,转发对象是谁)
3.methodSignatureForSelector:(1.返回方法签名,调用forwardInvocation,如果可以处理,转发结束 2.如果返回为nil,或者forwardInvocation无法处理,无法找到方法崩溃)

image.png

问题9:runtime如何通过Selector找到对应的IMP地址的?
首先查找当前实例对应类对象的缓存是否有Selector对应的IMP实现,如果缓存命中,就把命中的缓存函数返回给调用方。如果缓存没有命中。根据当前类的方法列表查找Selector对应的IMP事件。当前类如果没有命中,再根据当前类的superClass指针逐级查找父类的方法列表。然后查找Selector对应的IMP事件。

问题10:@dynamic (动态方法解析)
相当于在运行时添加set get方法。而不是在编译时声明好

动态运行时语言将函数决议推迟到运行时
编译时语言在编译期进行函数决议

相关文章

网友评论

      本文标题:iOS runtime详细内容

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