iOS底层分析之类的加载(下)

谐和学习!不急不躁!!我是你们的老朋友小青龙~

前一篇文章iOS底层剖析之类的加载(中)剖析了ro、rw的初始化以及分类的实质,本文针对分类的加载翻开进一步的根究。
上篇文章,咱们剖析到:rwe的初始化是在extAllo源码本钱cIfNeeded函数,调用extAllocIfNeeded函数有好几个当地:

  • attachCategories函数(将类别的特征、协议、办法增加到类)

  • demangledName函数

  • class_se宫颈癌tVersion函数(类的版别设置)

  • addM指针式万用表图片ethods_finish函数(增加办法)

  • class_addProtocol函数(增加协swift怎样读议)

  • _class_addProperty函数(增加特征)

  • objc_duplicateClass函数

增加特征、办法、协议等会调用extAlswiftkeylocIfNeeded函数,让我不由想到了文章《iOS类里边的数据为什么要分为ro、rw、rwe?》指针数学的一句话:

  • 因为工作时的存在,Methods、Protocols、Properties都是能够经过category手动源码精灵运用API,动态增加、批改,所以rw里也存了一份这些数据。

而rwe是rw的优源码是什么意思化,所以能够理解为:

  • category手动运用API批改/增加Methods、Protocols、Properties等会触发extAllocIfNeeded函数,google然后给rwe赋值。

回归正题,咱们要根究的是跟categios8备忘录ory有关的,中心函数是attachCategories,而调用到attachCategories的函数有ios1471值得更新吗两个:

  • attachToClass
  • load_categories_nolock
查看哪里调用了attachToClaios是什么意思ss

objc源码工商银行attachToClass,发现只要methodizeClass这个函数内部调用了:

iOS底层剖析之类的加载(下)

这儿有个ios体系if判别,咱们需求知道previously值,发现它是由mios体系ethodizeClass函数第二个参数传进来的。

持续查找methodizeClass

iOS底层剖析之类的加载(下)

跟上面相同,也是函数之间参数的传递,持续查找realizeClassWithoutSwift

iOS底层剖析之类的加载(下)

把上面寻找的进程画了个图:

iOS底层剖析之类的加载(下)

回到methodizeClass函数(参数preswiftcode是什么意思中文viously为nil):

static void methodizeClass(Class cls, Class previousios模拟器ly){
...
// 经过上传的根究,承认previously为nil
if (previ狗狗币ously) {
    if (isMeta) {
      objc::unattachedCategories.attachToClass(cls, previously,
                          ATTAC指针式万用表的使用办法图解H_METACLASS);
    } elseswiftly {
      objc::unattachedCategories.attachToClass(cls, previously,
                          ATTACH_CLASS_AND_METACLASS);
    }
  }
  objc::unattachedCategories.attachToClass(cls, cls,
                      isMeta ? ATTACH_MEswift代码是什么意思TACLASS : ATTACH_CLASS);
...
}

等于说调用attachT宫崎骏oClass的当地只要这一个当地:

static vo工商银行客服电话id met指针式万用表的使用办法图解hodizeClasswift世界结算体系s(Class cls, Class previous指针ly){
...
objc::unattachedCategories.attachToClass(cls, cls,
                      isMeta ? ATTACH_METACLASS : ATTACH_CLASS);
...
}
指针数组查哪里调用了load_categories_nolock

objc源码查找load_categories_nolock,发现这有这指针万用表哪个品牌的最好两个当地调用工商银行客服电话了:

  • loadAllCateswiftergories
  • _read_images
static void loadAllCategories() {
...
load_categoriesswiftly_nolock(hi);
...
}
void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses){
...
load_categories_nolock(hi);
...
}

拾掇一下调用attachCategories的两条线:

  • realizeClassWithoutSwift -> methodizeClass -> atios手游下载渠道tachToClass -> attachCategories

  • load_categorieswift代码s_nolock -> attachCategories

categoryswift选手的load办法结束与否

咱们知道,Class依据是否结束load办法,分为懒加载指针式万用表的使用办法图解类和swift世界结算体系非懒加载类,那么category是否公积金也有这样的差异呢?
依据前面剖析,swift怎样读调用attachCategorieios手游下载渠道sswift代码的当地分别是realizeClassWithoutSwiftload_categories_noios1471值得更新吗lockswiftcode是什么意思中文。咱们在这几个当地打上断点:

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

查验一:主类结束指针数组load办法,category结束load办法

工作代码:

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

所以咱们得出这样一条走向道路:

graphSwift TD
_read_images --> realizeClassWithoutSwift --> methodizeClas工商银行客服电话s --> attachToClass --> load_categories_nolock --> attachCategories
查验二:主类结束load办法,category不结束load办法

把category源码之家里的load办法注指针万用表哪个品牌的最好视,工作代码,然后会发现走向如下:

  • _swiftcode是什么意思中文read_images
  • realizeClassWitios是什么意思houtSwift
  • metho源码精灵dizeClass
  • attachToClass
  • 结束

它并没有走attachCategories这个函数。

查验三:主类不结束load办法,categor源码y结束load办法

相应的处理主类和分类的load办法,工作代码,会发现走向如下:

  • _read_images
  • realizeClassWithoutSwift
  • methodizeClass
  • attachToClass
  • 结束

和第二种查验作用相同

查验四:主类不结束lo指针式万用表的使用办法图解ad办法,category不结束load办法

ios14.4.1更新了什么应的处理主类和分类的load办法源码年代训练怎样样,工作代码:

iOS底层剖析之类的加载(下)

ios8备忘录验总结:要实施attachCa源码资源站tegories,需求「主类」和「分类」都结束lo公积金ad办法

category的数据在什么时分加载到主类

前面的查验是为了让咱们知道:load办法结束与否,它的流程走向。咱们实在关怀的是category的数据是什么时分加载到ro里源码精灵

针对查验一剖析(主类load、分类load)

咱们知道,类的数据读写分配是在realizeClassWithoutSwift函数:

static Class realizeClassWithoutios15Swift(Class cls, Class previos体系iously)
{
...
/******* 辅佐代码Direction  START *********/
  const cha指针万用表哪个品牌的最好r * class源码网站Name = "Direction";
  if (strcmp(class_getName(cls), className) == 0)
  {
    printf("I'm Dgoogleirection...");
  }
  /******* 辅佐代码Direction  E狗狗币ND *********/
auto ro宫颈癌前期症状 = (const class_ro_t *)cls->data();
...
}

下断点,控制台打印ro数据:

iOS底层剖析之类的加载(下)

第二遍进-》
iOS底层剖析之类的加载(下)

控制台指令如下:

p ro
p *$0
p $0->baseMethods(swiftcode是什么意思中文)
p *$2
p $3.get(0).big()
p $3.指针式万用表图片get(1).big工商银行()
p $3.get(2).big()
p $3.swift言语get(3).big()
// 图片上显现$4,是因为我前面有一步输入差错,流程没问题

从上图swiftcode是什么意思中文咱们能够看到,「realizeClassWithswiftlyoutSwift」函数并没有将分类数据加载到主类。

依照前面流程,接下来应该是走methoios体系dizeClass函数:

iOS底层剖析之类的加载(下)

咱们发现「metSwifthodizeClass」函数,仍是没有加载category数据。

持续进入下一个流程attachToClass函数:

iOS底层剖析之类的加载(下)

咱们发现「attachToClass」函数,仍是没有加载caios14.7正式版tegory数据。
放过断点,发现它又走了一遍methodizeClass源码编辑器 -->源码买卖网站源码 attachToClass

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

持续进iOS入下一个流程load_categories_ios是什么意思nolock函数:

经过断点定位到Direction类,经过methoios8备忘录dsForMeta函数得到cat里的元类办法列表
iOS底层剖析之类的加载(下)

经过methodsForMeta函数得到cat里的实例办法列表

iOS底层剖析之类的加载(下)

再来对比下ca源码精灵tegory里的办法:

iOS底层剖析之类的加载(下)

由此,咱们猜想:

  • category的办法是在load_ios1471值得更新吗categories_nolock函数里,装载到类里的。

断点持续往下走,会发现进入一个attachCategories函数。

根究attachCategorios体系ies做了什么事情

断点持续往下走:

iOS底层剖析之类的加载(下)
咱们发现会调用attachLists函数,榜首个参数是个二维指针

接下来在attachLists指针万用表的使用办法视频教程函数打上断点,并经过断点一指针c言语步步往下走:

iOS底层剖析之类的加载(下)

发现进入到源码之家这一段代码:

void attachLists(List* const *指针 addedLists, uint32_t addedCount) {
...
else {
// 1 list -&swift代码是什么意思gt; many lists
Ptr<List> oldList = list;
// oldList有或许为nil
uint32_t ol源码本钱dCount = oldList ? 1 : 0;
uinios15t32_t newCount = oldCou指针nt + addedCount;
setArray((array_t *)malloc(array_t::byteSize(newCount)));
array()->count = newCount;
// 将oldList全体刺进到下标为added指针式万用表Coun工商银行t的方位,addedCount是category的办法个数,也便是当时函数传入来的第二个参数
if (oldList) array()->lists[addedCount] = oldiOSList;
for (unsigned i = 0; i < addedCount; i++)
// 遍历将addedCount的元素,从0下标开始刺进
array()->lists[i] = addedLists[i];
validate();
}
...swift言语
}

控制台打印下list:

iOS底层剖析之类的加载(下)

控制台打印下oldList:

iOS底层剖析之类的加载(下)

控制台打印下addedLists:

iOS底层剖析之类的加载(下)

  • list为空枸杞
  • oldList寄存的是主类的办法类表。
  • addedLists前面现已剖析过了,ios14.4.1更新了什么它是一个二维ios手游下载渠道指针,毕竟指向的是cateogry里的办法列表swift怎样读

断点持续走:

iOS底层剖析之类的加载(下)

咱们发现,array()->lists里边寄存的不是一个个method_list_t,而是一个ios手游下载渠道个method_list_t指针。为了验证这一点,咱们持续打印:

iOS底层剖析之类的加载(下)

咱们再来看看array()-&指针式万用表图片gt;swiftlylists[0]寄存着什么:

iOS底层剖析之类的加载(下)

array寄存着cswiftkeyategory方ios模拟器法列表的指针。

针对查验二剖析(swift世界结算体系主类load、分类无load)

查验作用和针对查验三剖析相同。

针对查验三剖析(主类无load、分类load)指针万用表的使用办法视频教程

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

得出结论:

  • 主类未结束load办法,分类结束load办法的状况下,category的数据伴随着image的加载,直接写到data()里;
针对查验四剖析(主类无load、分类无load)

发现程序一发起,没有进_read_images函数断点、也没有进realizeC源码资源站lassWitho源码年代utSwift函数Swift断点。
iOS底层剖析之类的加载(下)

放过断点 进入下一步”

iOS底层剖析之类的加载(下)

咱们发现,main.m里实源码精灵行了Direction *dr = [Dire指针c言语ction alloc];相当于发送了一个alloc音讯,详细概龚俊况能够点击左面栏:

iOS底层剖析之类的加载(下)

小断点,移动到实施完ro赋值,然后控制台打印ro:

iOS底层剖析之类的加载(下)

得出结论:当主类和分类都没有结束load办法,category的数swift代码据绑定推迟到榜首工商银行次发送消swifter息。

概括以上4个查验,对cios14.7正式版ategory办法什么时分加载,做一个拾掇:
  • 主类和分类都结束load办法: attachCategories加载

  • 主类结束load,宫颈癌分类不结束load办法:d源码年代ata()读取的时分加载

  • 主类不结束load,分类结束load办法:data()读取的时分加载

  • 主类和分类都不结束load办法:榜首次音讯发送的时分加载

拓展:主类宫颈癌前期症状结束loswift代码ad,一个分类结束load,另一个分类不源码编辑器结束load

指针竟仍是会走到这儿:

iOS底层剖析之类的加载(下)

这儿的count抉择着对多个category进行处理,那指针数学么count数值来自哪里呢?咱们发现在当时函数下,有着两行代码:

iOS底层剖析之类的加载(下)

processCatlist是一个相似block的声明,因为实施了processCatlist(hi->catlist(&amp指针式万用表;count));ios是什么意思这行代码,才会触发里边的for循环。

持续进入catlist

category_t * const *header_info::catlist(size_t *outCount) cons狗狗币t
{
...
return _getios手游下载渠道Objc2CategoryList(mhdr(), outCount);
...
}

iOS底层剖析之类的加载(下)

阐明count的数据是从mach-O里边读取的__objc_catlist字段数据。

由此,我宫颈癌们能够get到一个点:

  • loaios手游下载渠道d办法乱写,会增加程序发起进程中的背负ios8备忘录,延伸发起时刻。
多个分类

实际进程中,关于一个类,或许存在多个分类,咱们在原本一个分类的基础之上,再增加指针数学以一个分类Direction+categoryTwo

// Direction+categoryTwo.h
@interface Direction (categoryTwo)
- (void)look_categoryTwo;
- (iOSvoid)dreamSome_categoryTwo;
+ (void)cleanSome_categoryTwo;
@end
// Direction+categoryTwo.m
#import "Direction+c指针式万用表的使用办法图解ategor指针式万用表yTwo.h"
@implement指针c言语ation Direction (categoryTwo)
- (void)look_categoryTwo{
NSLog(@"Direction (categoryTwo)---look_categoryTwo");指针式万用表
}
- (void)dreamSomios8备忘录e_categoryTwo{
NSLoGog(@"Direction (categoryTwo)---dreamSome_categoryTwo");
}
+ (void)cleanSome_categoryTwo{
NSLog(@"DiriOSection (categorios是什么意思yTwo)---cleanSome_categoryTwo");
}
@end

咱们依旧是从load_categories_nolock函数开始剖析(前面现已剖析过了):

iOS底层剖析之类的加载(下)
经过奉告台打印,发现i=0的状况下,cat的姓名是categoryTwo,再查看
Build Phases:

iOS底层剖析之类的加载(下)

能够得出一个结论:

  • category的加载次序是看Build Phases的先后次序

言归正传,咱们要剖析的是多个c源码本钱ategory的走向,i=0(也便是category只要一个)的状况咱们前面剖析过了,咱们想根究的是当i=1乃至i=2等等的流指针c言语程走向,(这儿取i=1进行剖析)。

持续走断ios模拟器点……咱们要看的是attachLists函数,看看会不会进入if (hasArray()) {这个句子ios1471值得更新吗块:

iOS底层剖析之类的加载(下)

发现它进入了,咱们还趁便打印了下addedLists参数的内容。
持续查看arra源码编辑器y~

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

所以能够看到,array顺次保存着两个元素:

  • 指向category办法列表的指针
  • 指向本类办法ios体系列表的指针

持续剖析:

iOS底层剖析之类的加载(下)

再结合上图array里保存的数据,我源码年代训练怎样样们能够得出一个结论:
当存在多个cswiftlya源码年代tegory的状况,array内部会依照先后次序摆放:categoryX办法列表指针、categoryXX办法列表指针….本类办法类表指针。

经过上图剖析,咱们得出l指针数学ist的内存结构大概是这样的工商银行客服电话

objc源码查找attachCategories

//将办法列表、特征和协议从类别附加到类swift言语
//假定cats中的类别都已加载并按加载次序排序,
//首swiftcode是什么意思中文先是最陈腐的类别。
static void
attachCategories(Class cls, const locstamped_category_t *cats_list, uint32_t cats_count,
        int flags)
{
...
// **ios是什么意思******* 针对性剖析,咱们研究的是Direction *********
/// 辅ios14.4.1更新了什么佐代码  START *********/
  const char *mangledName = cls->nonlazyMangledName();
  const char *comName = "Direction";
  if (strcmp(comName, mangledName) == 0) {
    //经查验,假定category里Swift面不结束+load办法,不会进入这儿
    printf("类的公积金加载处理|| mangledName-->%sn",mangledName);
  }
  /// 辅佐代码  END *********/
// 中心代码
  f源码是什么意思or (uint32_t i = 0; i < cats_c源码是什么意思ount; i++) {
    /**** 办法处理 ***/
    au宫颈癌前期症状to& entry = cats_list[i];///遍历一个个category,得到category地址&entry
    // methodsForMeta:假定是元类,回来类办法列表;不然回来实例办法列表
    method_iOSlist_t *mlist = entry.cat->methodsForMeta(isMeta);
    if (mlist) {
      // 判别mcount(category总个数)是否等于64,假定为真就进入句子块
      if (mcount == ATTACH_BUFSIZ) {
        // cls:  类或元类
        // mlists: 从category读取的办法列表,或许是类办法列表,也或许是实例办法类表;
        // prepareMethodLists内部:调用fixupMethodList,结束对mlists的SEL绑定、办法排序
       
prepareMethodLists(cls, mlists, mcount, NO, fromBundle, __func__);
        // 将category宫崎骏的办法列表追加到类的办法列表后边
        rwe->methods.attachLists(mlists, mcount);
        mcount = 0;
      }
     
// 榜首个从下符号63的方位,开始刺进 -- 也便是倒着刺进 (ATTACH_BUFSIZ = 64)
      mlists[ATTACH_BUFSIZ - ++mcount] = mlist;//这一行,mcouios14.7正式版nt会做累加
// 类的header信息
      fromBundle |= entry.hi->isBundle()源码是什么意思;
    }
   
/**** 特征处理 ***/
    // 依据isMeta,回来: 类指针特征列表 或 实例特征列表
    property_list_t *pr指针式万用表oplist =
      ent源码ry.cat->propertiesForMeta源码是什么意思(isMeta, entry.hi);
    if (proplist) {
      i工商银行客服电话f (propcount == ATTACH_BUFSI工商银行客服电话Z) {
        // 将category的特征列表追加到类的特征列表后边
        rwe->properties.at指针式万用表的使用办法图解tachLists(proplists, propcount);
        propcount = 0;
      }
      // 跟mlswiftlyists相同,也是从下表63的方位,向前倒着刺进
      proplists[ATTACH_BUFSIZ - ++propcoun指针数组t] = proplist;
    }
   
/**** 协议处理 ***/
    // 依据isM源码精灵eta,源码是什么意思回来: 空 或 协议列表
    // 留心:元类没有协议
    protocol_list_t *protolist = entry.cat->protocolsForMeta(isMeta);
    if (protoGolist) {
      if (protocount == ATTACH_BUFSIZ) {
        // 将category的协议列表追加到类的协议列表后边
        rwe->protocols.attachLists(protolists, protoios1471值得更新吗count);
        protocount = 0;
      }
      // 跟mlists相同,也是从下表63的方位,向前倒着刺进
      protolists[ATTACH_BUFSIZ - ++protocount] = protolist;
    }
  }
...
}

attachLists剖析

void attachLists(List* cios15onst * addedLists, uint32_t addedCount) {
...
// 榜首次ha指针式万用表sArswift选手ray或许为空
if (hasArray()) {
...
/指针万用表哪个品牌的最好/倒叙拆入,假定lists里现已有3个里,addedLists里有2个,那就
// newArray->list[4] = list[2]
// newArray->list[3] = list[1]
//源码是什么意思 newArray->list[2] = list[0]
// 流出来newArray->list[0]和newArray->list[1]是给addedLists工商银行寄存的
for (int i = oldCount - 1; i >= 0; i--)
newAr源码本钱ray->lists[i + addedCount] = array()->lists[i];
// addedLists里的从0开始刺进到newArrayios8备忘录->lists里
for (unsigned i = 0;ios下载 i < addedCount; i++)
newArray->lists[Swifti] = addedLists[i];
...
}
e指针c言语lseios体系 if (!list && addedCount == 1) {
// 假定list为空,且addedLists宫颈癌前期症状只要一个
      lisswift怎样读t = addedLists[0];
      validate();
}
else {
      // 1 list -> many lists
      Ptr<List> oldList = list;
      // oldList有或许为nil
      uint32_t oldCount = oldList ? 1 : 0;
      uint32_t newCount = oldCount + addedCount;
      setArray((array_t *)malloc(array_t::byteSize(newCount)));
      arr宫崎骏ay()->count = newCount;
      // 将oldList全体刺进到下表为addedCount的方位,addedCount是category的办法个数,也便是当时函数传入来的第源码资源站二个参数
      if源码网站 (oldList) array()->lists[addedCount] = oldList;
      for (unsigned i = 0; i < addios体系edCount; i++)
        // 遍历将addswiftcode是什么意思中文edCount的元素,从0下标开始刺进
        array()->lists枸杞[i] = addedLists宫颈癌[i];
      validate();
    }swift世界结算体系
}

iOS底层剖析之类的加载(下)

咱们能够发现,attachLists函数的意图是:把catego指针c言语ry的List刺进到原本List的最前面。

attachCategories代码的静态剖析现已结束,接下来开始实操、下断点、控制台打印验证:

  • 下断点

iOS底层剖析之类的加载(下)

工作工程,等进入榜首个断点,阐明其iOS时cls是Direction类,然后把第swift代码是什么意思二个断点翻开:

iOS底层剖析之类的加载(下)
这边能够看一下category里的内容:

iOS底层剖析之类的加载(下)

iOS底层剖析之类的加载(下)

放过断点,会再一次进入attachCategories函数,依照前面一次的姿态打印mlist:

iOS底层剖析之类的加载(下)

如此看来:

  • isM指针式万用表图片eta为fals源码网站e,methodsForMeta(isMeta)Swift回来的是分类-实例办法列表

  • isMeta为true,methodsForMeta(isMeta)回来的是分类-类办法列表

特征列表也相同的操作

iOS底层剖析之类的加载(下)

第二次进断点,元类打印为nil,因为当时没有类特征。

本文总结

  1. 针对主类和分类是否结束load办法,衍生出了4种(多个分类这种没算上)状况。
  2. 针对不同的状况,经过断点大概有了一个走位了解。
  3. 经过断点,控制台ro的打印,定位category办法是什么时分加载。
  4. 剖析多个cat指针万用表的使用办法egory,详细的流程走向,ios模拟器及attachCategories和attachLists的源码剖析

代码:

链接: pan.baidu.com/s/1cXT7f_Na…
暗码: mu1m
–来自百度网盘超级会员V2的同享

发表评论

提供最优质的资源集合

立即查看 了解详情