美文网首页
07--应用加载03--类的加载

07--应用加载03--类的加载

作者: 修_远 | 来源:发表于2020-07-21 23:51 被阅读0次
    TOC

    readClass 流程

    readClass 注释

    1. 未来类的处理

    虽然这个分支里面设置了 ro/rw,但是正常情况下是不会进来这个分支的,所以可以认定 ro/rw 不是在这里设置的。

    未来类的处理 注释
    1. 读取 classdata() 段,设置 ro/rw
    2. 对新类做重映射
    3. 使用新类

    2. addNamedClass 将类插入gdb_objc_realized_classes总表中

    image

    3. addClassTableEntry 将类插入allocatedClasses类表中

    image

    4. 返回cls

    返回结果有以下三种情况

    • 原来的类:cls
    • 空的类:nil (cls has a missing weak-linked superclass)
    • 新的类:something else (space for this class was reserved by a future class)

    realizeClassWithoutSwift 流程

    【注释以及说明】

    1. 从命名来看,在swift版本肯定有一个 realizeClassFromSwift 方法
    2. 类cls 上执行首次初始化,包括 ro-rw 的数据分配
    3. 不执行任何 swift端 的初始化
    4. 返回类的真实结构
    5. runtimeLock必须被调用者写锁定

    1. 创建rw,对ro赋值,这里并没有对rw里面的重要参数赋值

    image
    • future 类,第一流程出现过
    • normal 类

    2. 递归实现supercls和metacls

    image 递归出口

    学习总是环环相扣,Isa走位图中,NSObject的父类指向nil,在这里验证了

    3. 更新父类和元类

    image

    4. 关联这个类到父类的子类列表中

    image
    • 如果有父类,则将cls添加到父类中:addSubclass(supercls, cls);
    • 如果没有,说明本身是根类,则将cls添加到根类列表中:addRootClass(cls);

    5. 附加类别,将ro的内容拷贝到rw

    image
    1. 修复cls的方法列表、协议列表和属性列表
    2. 附上任何未完成的类别
    3. runtimeLock必须由调用者持有

    attachLists 流程

    attachLists源码

    1. 将多个元素的数组添加到多个元素的数组

    • 扩容数组

      setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
      
    • 将旧数组移到最后

      memmove(array()->lists + addedCount, array()->lists, oldCount * sizeof(array()->lists[0]));
      
    • 将新的数组拷贝到前面

      memcpy(array()->lists, addedLists, addedCount * sizeof(array()->lists[0]));
      

    2. 将单个元素添加到空数组中

    • 直接取第一个元素作为新数组

      list = addedLists[0];
      

    3. 将多个元素的数组添加到单个元素的数组

    • 扩容数组

      setArray((array_t *)malloc(array_t::byteSize(newCount)));
      
    • 把那一个旧的移到末尾

      if (oldList) array()->lists[addedCount] = oldList;
      
    • 将新的数组拷贝到前面

      memcpy(array()->lists, addedLists,  addedCount * sizeof(array()->lists[0]));
      
    method_array_t
    • memcpy 函数:从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中

    4. 除了在加载类的时候会调用:attachLists还有哪些情况

    • 类的加载:处理方法、属性、协议 methodizeClass
    • 添加方法:addMethods
    • 添加属性:_class_addProperty
    • 添加协议:class_addProtocol
    • 分类的加载:attachCategories

    补充

    元类递归出口条件

    元类递归 image
    • 判断为假
    • 初始化一个元类,在表中没有找到,就返回for循环中的内容

    ro-rw 相关知识点

    image

    objc_registerClassPair 的时候会改变这些标记,这些标记保证 ro 中的数据不会被修改

    // cls->ISA()->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
    // cls->changeInfo(RW_CONSTRUCTED, RW_CONSTRUCTING | RW_REALIZING);
    
    1. 添加成员变量class_addIvar 必须放在 objc_registerClassPair 将类注册到内存之前
      因为成员变量存在ro 的 ivarlist中,类注册到内存中便无法修改了
    2. objc_registerClassPair 之后也可以注册属性,因为属性存在 rwproperty 列表中
    3. 如果只添加成员变量,没有添加对应的 setter、getter 方法是不能使用 KVC赋值 的。(如果没有 68、69行的代码,第80、81行会报错)

    相关文章

      网友评论

          本文标题:07--应用加载03--类的加载

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