類的加載(下)

在上一篇文章類的加載(上)了解了到了_read_images大概流程咽块,也詳細講解了readClass方法 技能回顧

map_images函數(shù)實現(xiàn)類加載處理標紅.jpg

下面講解 標紅區(qū)域 因為講的是類的加載,當類的加載了解清楚了 其他步驟 也就清晰可見

懶加載類和非懶加載類

首先我們看類加載處理這里的源碼

類的加載處理源碼注釋

在源碼注釋里我們很清晰的看到了一句話 Realize non-lazy classes (for +load methods and static instances) 翻譯過來 就是 實現(xiàn)非懶加載類(當實現(xiàn)了+load方法 或者 static instances)?
帶著疑問 我們修改源碼 在 類的加載(上)我們曾在readClass里面也進行了修改 這次我們在 下面繼續(xù)斷點 并 修改源碼目的針對性研究
截屏2020-10-20 下午1.31.55.png

非懶加載類環(huán)境流程

將LGPerson里的項目 添加上+load 運行 按照源碼所說 此時它為非懶加載類


截屏2020-10-20 下午1.35.40.png

項目斷在readClass 并繼續(xù)過斷點


截屏2020-10-20 下午1.37.20.png

截屏2020-10-20 下午1.40.48.png

我們看到確實來到了修改源碼的斷點 并即將進入 realizeClassWithoutSwift 函數(shù) 下面我們進行研究

realizeClassWithoutSwift

源碼注釋此方法的含義


截屏2020-10-20 下午1.47.10.png

解讀

  • 首次對類cls進行初始化,
  • 包括分配讀寫數(shù)據(jù)芳来。
  • 不執(zhí)行任何快速端初始化构回。
  • 返回類的真實類結構驰凛。

源碼查看及解讀 (由于代碼太長分段解讀)


截屏2020-10-20 下午1.57.22.png
第一步:讀取data數(shù)據(jù)
  • 當前類的判空 是否已經(jīng)實現(xiàn) 的判斷
  • 未實現(xiàn)也不為nil 讀取 class的data數(shù)據(jù) 并強轉為 (class_ro_t*)類型 獲取 ro
  • 獲取元類判斷條件
  • 如果是未來的類 剪芥,此時 rw 數(shù)據(jù) 已經(jīng)準備好 直接讀取 data() 獲取 rw ro
  • 正常的類 分配可寫入的類數(shù)據(jù)。
    1. 申請開辟 <class_rw_t>數(shù)據(jù)結構 rw模板
    2. 根據(jù)ro設置rw 從ro中copy到rw中
    3. 將cls的data賦值為rw形式
第二步:遞歸調用 realizeClassWithoutSwift 完善 繼承鏈
截屏2020-10-20 下午2.29.45.png
  • 遞歸調用 realizeClassWithoutSwift設置父類剃幌、元類
    注: isa找到根元類之后聋涨,根元類的isa是指向自己,并不會返回nil负乡,所以有以下遞歸終止條件牍白,其目的是保證類只加載一次
    1.如果類不存在,則返回nil

    2.如果類已經(jīng)實現(xiàn)抖棘,則直接返回cls
    截屏2020-10-20 下午2.38.53.png
    1. remapClass 如cls不存在茂腥,則返回nil
      截屏2020-10-20 下午2.41.06.png
  • 設置父類和元類的isa指向

  • 通過addSubclass 和 addRootClass設置父子的雙向鏈表指向關系,即父類中可以找到子類切省,子類中可以找到父類

第三步:通過 methodizeClass 方法化類

源碼注釋此方法的含義



截屏2020-10-20 下午2.49.43.png
  • 修復cls的方法列表最岗、協(xié)議列表和屬性列表。
  • 附加任何突出類別朝捆。

源碼查看及解讀


截屏2020-10-20 下午3.28.43.png
  • 在realizeClassWithoutSwift 我們已經(jīng)拿到了 ro rw 沒見到 rwe的蹤影
  • method_list 方法處理
    注:在這里 我們想起了在 消息發(fā)送流程的慢速查找流程般渡,其中查找算法是二分查找,說明sel-imp是有序排列,那么如何排序的呢驯用?
    就是在這里
    截屏2020-10-20 下午3.38.54.png

    它內部是通過fixupMethodList方法排序
    截屏2020-10-20 下午3.41.01.png

    進入fixupMethodList源碼實現(xiàn)脸秽,是根據(jù)selector address排序
    截屏2020-10-20 下午3.43.11.png
  • 無論是methods 還是properties 還是protocols 我么發(fā)現(xiàn)都去調用了一個方法attachLists添加上針對的代碼 并斷點到LGPerson
    截屏2020-10-20 下午4.05.32.png

結果發(fā)現(xiàn) rwe 為NULL 并未運行其 rwe為真的判斷 為什么 留疑問

  • 繼續(xù)過斷點來到了 attachToClass


    截屏2020-10-20 下午4.11.02.png

    截屏2020-10-20 下午4.19.50.png

    在methodlist方法主要是將分類添加到主類中 當前環(huán)境沒有分類所以下面都沒有運行

懶加載類環(huán)境流程

??上面的流程我們都是在實現(xiàn)了load的情況下進行跟進的下面??我們來屏蔽load使其變?yōu)閼屑虞d環(huán)境


截屏2020-10-20 下午10.23.29.png

并在初始化LGPerson代碼斷言 運行


截屏2020-10-20 下午10.29.57.png

發(fā)現(xiàn) 在main函數(shù)之前調用的 mapimages -> _read_images -> readClass
在次向下走一步斷點
截屏2020-10-20 下午10.43.28.png

進入到methodizeClass里查看調用棧


截屏2020-10-20 下午10.48.33.png

這不正是我們之前學習的消息慢速轉發(fā)流程lookImpOrForward發(fā)起的調用嘛

總結

  • 什么是懶加載類 和非懶加載類
    截屏2020-10-20 下午10.51.39.png
  • ro rw rwe 定義及為什么存在
    1. app在使用類時,是需要在磁盤中app的二進制文件中讀取類的信息蝴乔,二進制文件中的類存儲了類的元類记餐、父類、flags和方法緩存 那么類的額外信息(name薇正、方法剥扣、協(xié)議和實例變量等)存儲在class_ro_t中

    2. class_ro_t簡稱 ro: read only 干凈的內存空間 只讀 又稱為 clean memory

    3. class_rw_t簡稱 rw: read write 意義: 由于ios有運行時 會不斷的插入 添加 刪除 也就是 增刪改 查 頻繁 對當前 這塊內存操作比較嚴重 為了防止對原始數(shù)據(jù)的破壞,所以就有了 rw 用于讀寫編寫程序铝穷。 drity memory 在進程運行時發(fā)生更改的內存。類一經(jīng)使用運行時就會分配一個額外的內存佳魔,那么這個內存變成了drity memory曙聂。但是在實際應用中,類的使用量只是10%鞠鲜,這樣就在rw中造成了內存浪費宁脊,所以蘋果就把rw中方法、協(xié)議和實例變量等放到了class_rw_ext_t中贤姆。

    4. class_rw_ext_t簡稱 rwe: read write ext榆苞,用于運行時存儲類的方法、協(xié)議和實例變量等信息霞捡。


      class ro - rw - rwe.jpg

分類的加載流程

attachToClass

在methodlist方法主要是將分類添加到主類中坐漏,其源碼實現(xiàn)如下


截屏2020-10-20 下午11.05.34.png
  • 找到一個分類進來一次,即一個一個加載分類碧信,不要混亂
  • 當主類沒有實現(xiàn)load, 分類開始加載赊琳、迫使主類加載,會走到if流程
    下面研究 attachCategories

attachCategories

截屏2020-10-21 下午4.58.58.png

源碼注釋解析

  1. 將方法列表砰碴、屬性和協(xié)議從類別附加到類中躏筏。
    假設所有cats中的類別都已加載并按加載順序排序,
    先有最古老的類別呈枉。

  2. 只有少數(shù)類在啟動期間有超過64個類別趁尼。
    這使用了一個小堆棧,并避免malloc猖辫。

    類別必須按正確的順序添加酥泞,也就是從后到前。為了完成分塊操作住册,我們從前向后迭代cats_list婶博,向后構建本地緩沖區(qū),并在塊上調用attachLists。attachLists突出顯示的
    列表凡人,因此最終結果按照預期的順序名党。

截屏2020-10-21 下午5.09.28.png

在這里我們看到了 rwe 賦值

截屏2020-10-21 下午5.19.08.png
  • 判斷rwe是否存在,存在直接取值不存在 則根據(jù)ro開辟挠轴。


    截屏2020-10-21 下午5.26.46.png

點進去我們也看到了 attachLists方法 從0-1的過程也存在下面進行分析它

attachLists

截屏2020-10-21 下午5.40.21.png

經(jīng)過分析 我們可以看到 attachLists 方法存在三種情況 下面為 rwe 方法列表 0 -1的過程


rwe方法列表 0-1

回到上面斷點處 我們打印 rwe


截屏2020-10-21 下午6.24.57.png

此時沒有走下面的時候 rwe的 methods 正是 本類也就是ro->baseMethods 數(shù)據(jù)的 copy
我們繼續(xù)向下走


截屏2020-10-22 上午10.51.07.png

畫圖表示 這個算法


category存入 64個空間的 mlists
  1. 先存進之前開辟好的64個空間的棧里
  2. mlists + ATTACH_BUFSIZ - mcount 獲取mlists的首地址+ 64 - 有幾個分類 最終等于 這幾個分類的真實地址传睹。抹掉沒用到的。
  3. 排序
  4. 存入到rwe的methods中.
    1). 從上面的0-1 過程 就是 開始創(chuàng)建 rwe 將本類 ro中的baseMethods存入rwe中 此時 attachlists 是 0-1 是一個 一緯數(shù)組岸晦。
    2). 這次再進入 就是一個 1對多 的過程欧啤。


    list ->many Lists

在下面是 多對多的邏輯示意圖


截屏2020-10-22 下午1.15.14.png

總結

  • readClass 主要是讀取類,即此時的類僅有地址+名稱启上,還沒有data數(shù)據(jù)
  • 懶加載類 未實現(xiàn)load的的類 數(shù)據(jù)加載推遲到第一次消息的時候
  • 非懶加載類 map_images的時候 加載所有的類數(shù)據(jù)
  • methodizeClass 兩種情況都會調用 一個是main函數(shù)之前 一個是消息發(fā)送之慢速查找邢隧。
  • 在mehodizeClass里 方法序列化 為了 在慢速查找中的二分查找, 有附加分類 方法 冈在,主要是將 rwe的初始化(從ro中獲取主類初始值)倒慧、將主類的 methods、 properties包券、 protocols 等添加到 rwe中纫谅, 其帖進去的方法核心為 attachLists函數(shù)算法

類的加載源碼解析分析圖

類加載處理.jpg

上面我們已經(jīng)大概理解了類是如何從Mach-0 加載到內存中,下面我們來詳細了解 分類 如何加載到類中溅固,以及 類 + 分類搭配使用情況

分類的本質

通過 clang 以及 蘋果官方文檔 及 objc源碼 我們都可以了解到分類的本質就是一個結構體
截屏2020-10-22 下午6.15.17.png
  • instanceMethods: 實例方法列表
  • classMethods: 類方法列表
  • protocols: 協(xié)議表
  • instanceProperties: 實例屬性 表
  • _classProperties : 類屬性表 付秕; 拓: @property(class,nonatomic,copy) NSString * classPropertie
  • methodsForMeta() : 獲取方法列表 判斷是否是元類 還是 類。(因為我們知道 實例方法在類中侍郭,類方法在元類中)
  • propertiesForMeta() 獲取元類或者類的屬性 表
  • protocolsForMeta() 獲取 元類 或者 類的 協(xié)議表 (從這里可以看出協(xié)議只存在類對象中)

分類的調用時機

上面的流程分析了 attachCategories的源碼干了點什么事情它主要是 是否存才 rwe 不存在 初始化rwe 及 將分類的信息 帖到 rwe中 下面是它的流程
realizeClassWithoutSwift -> methodizeClass -> attachToClass -> attachCategories
上面支線我們已經(jīng)跑通 下面來全局搜索 attachCategories 看哪里還用到了它經(jīng)過我們的反推有了以下流程
load_images -> loadAllCategories -> load_categories_nolock -> attachCategories
示意圖


截屏2020-10-22 下午6.29.28.png
  • realizeClassWithoutSwift 方法 (已知)
    懶加載類的時候 是 由 lookUpImpOrForward 發(fā)起的調用
    非懶加載類的時候 是由 map_images 發(fā)起的

  • attachCategories 方法

    1. 首先必要條件是研究的這個類存在分類(已知)
    2. attachToClass 是由realizeClassWithoutSwift掉起的 什么情況下才會掉起 attachCategories ?
    3. 既然 有懶加載類 和 非懶加載 區(qū)別 那么 分類是不是也有询吴?
    4. 通過反推查看objc源碼 得知 load_images 也可以掉起 attachCategories?什么時機掉起的励幼?
  • 帶著上面已知和未知的問題 就引出了下面要講解的 類 和 分類搭配到的加載

類和分類搭配加載

首先配置環(huán)境主類 LGPerson

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *kc_name;
@property (nonatomic, assign) int kc_age;
- (void)kc_instanceMethod1;
- (void)kc_instanceMethod3;
- (void)kc_instanceMethod2;
+ (void)kc_sayClassMethod;
@end

NS_ASSUME_NONNULL_END

#import "LGPerson.h"
@implementation LGPerson
+ (void)load{
    
}

- (void)kc_instanceMethod3{
    NSLog(@"%s",__func__);
}

- (void)kc_instanceMethod1{
    NSLog(@"%s",__func__);
}

- (void)kc_instanceMethod2{
    NSLog(@"%s",__func__);
}
+ (void)kc_sayClassMethod{
    NSLog(@"%s",__func__);
}
@end

分類1 LGPerson+LGA

#import "LGPerson.h"
NS_ASSUME_NONNULL_BEGIN
@interface LGPerson (LGA)
- (void)cateA_1;
- (void)cateA_2;
- (void)cateA_3;
@end
NS_ASSUME_NONNULL_END
#import "LGPerson+LGA.h"
@implementation LGPerson (LGA)
+ (void)load{
    
}
- (void)kc_instanceMethod1{
    NSLog(@"%s",__func__);
}
- (void)cateA_2{
    NSLog(@"%s",__func__);
}
- (void)cateA_1{
    NSLog(@"%s",__func__);
}
- (void)cateA_3{
    NSLog(@"%s",__func__);
}
@end

分類2 LGPerson+LGB

#import "LGPerson.h"

NS_ASSUME_NONNULL_BEGIN

@interface LGPerson (LGB)
- (void)cateB_1;
- (void)cateB_2;
- (void)cateB_3;
@end

NS_ASSUME_NONNULL_EN
#import "LGPerson+LGB.h"

@implementation LGPerson (LGB)
+ (void)load{
    
}

- (void)kc_instanceMethod1{
    NSLog(@"%s",__func__);
}

- (void)cateB_2{
    NSLog(@"%s",__func__);
}
- (void)cateB_1{
    NSLog(@"%s",__func__);
}
- (void)cateB_3{
    NSLog(@"%s",__func__);
}

@end

1.非懶加載類 + 非懶加載分類

  • 首先 在 realizeClassWithoutSwift 寫下針對性研究LGPerson類的代碼 并在里斷點 看其調用堆棧


    截屏2020-10-23 下午12.56.46.png
  • 繼續(xù) 在methodizeClass 寫下針對性代碼 并在里斷點 看其調用堆棧


    截屏2020-10-23 下午1.03.22.png
  • 繼續(xù) 在attachToClass 寫下針對性代碼 并在里斷點 看其調用堆棧
截屏2020-10-23 下午1.09.56.png
  • 在下面打上新的斷點 并 在 attachCategories里到打下斷點


    截屏2020-10-23 下午1.18.36.png

    截屏2020-10-23 下午1.20.39.png

    過斷點 發(fā)現(xiàn) 上面我們標紅區(qū)域并沒有走 但是確實也來到了 attachCategories方法 確實也是LGPerson 我們仔細看堆棧情況


    截屏2020-10-23 下午1.26.31.png

    (1). 此時發(fā)現(xiàn) map_image掉起的流程已經(jīng)結束 并沒有調用 attachCategories汰寓。流程: map_image -> _read_images() -> realizeClassWithoutSwift -> methodizeClass ->attachToClass ->結束
    (2).而是由 load_image發(fā)起的調用流程:load_image -> loadAllCategories ->load_categories_nolock -> attachCategories
    (3).此時 rwe 有了值 我們bt 打印其 methods 發(fā)現(xiàn)其正是 對 ro->methods的數(shù)據(jù)拷貝 對于extAllocifNeeded()我們上面 也已經(jīng)詳細分析過了。

在下面繼續(xù)斷點跟蹤


截屏2020-10-23 下午2.07.18.png

1.發(fā)現(xiàn) cats_count =1 此時循環(huán)一次 分類的名字 為LGA 將分類中的方法 存入mists 的最后一位 上面有對此詳細的解答

  1. 將分類的方法 進行排序 并將 分類的方法存入到 rwe中 通過 attachLists方法 上面我們也有對attachLists算法的詳細解答

我們斷過上面 來到 1399 1400 方法 并將 1367 和1399 1400 斷點取消


截屏2020-10-23 下午2.21.37.png

繼續(xù)過斷點操作 發(fā)現(xiàn)此時斷點又斷回了attachCategories 中的針對性代碼區(qū)域


截屏2020-10-23 下午2.25.40.png

繼續(xù)打開 1367 1399 1400 向下走
截屏2020-10-23 下午2.30.11.png

1.發(fā)現(xiàn) cats_count =1 此時循環(huán)一次 分類的名字 為LGB 將分類中的方法 存入mists 的最后一位

  1. 將分類的方法 進行排序 并將 分類的方法存入到 rwe中 通過 attachLists方法

繼續(xù)取消 1367 和1399 1400 斷點 向下走 發(fā)現(xiàn)又回到了 realizeClassWithoutSwift


截屏2020-10-23 下午2.42.20.png

斷點到針對性代碼下面


截屏2020-10-23 下午2.46.18.png

繼續(xù)過斷點 發(fā)現(xiàn)再此處 cls->isRealized() 判斷了一下是否實現(xiàn) 實現(xiàn)返回cls 并沒有向下執(zhí)行 又回到了 realizeClassWithoutSwift方法對性代碼里


截屏2020-10-23 下午2.49.29.png

繼續(xù)過斷點 從判斷 cls->isRealized() 直接返回cls 整個流程跑完了程序進入了main函數(shù)
截屏2020-10-23 下午2.53.34.png

注:刪掉其他斷點留下針對性調試的斷點 我們下面還會用哦
總結:非懶加載類+ 非懶加載分類 : 首先map_image -> _read_images() -> realizeClassWithoutSwift -> methodizeClass ->attachToClass ->結束
在這條支線上并未對 分類進行什么操作 只是完成了類的加載
然后發(fā)起 load_image函數(shù)的回調 -> loadAllCategories ->load_categories_nolock -> attachCategories (在這里有多次調用有幾個非懶分類會調用幾次)將分類的數(shù)據(jù)貼到 rwe中苹粟,并再次發(fā)起了 realizeClassWithoutSwift(有幾個非懶分類會調用幾次)的調用 來判斷類是否已經(jīng)實現(xiàn)有滑。

2.非懶加載類 + 懶加載分類

  • 下面我們將源碼中 所有分類的load都去掉 使分類變?yōu)閼屑虞d概念 并運行 來到 realizeClassWithoutSwift 此時是由 map_images發(fā)起的調用


    截屏2020-10-23 下午3.49.37.png
  • 繼續(xù)過斷點 來到methodizeClass


    截屏2020-10-23 下午3.51.04.png
  • 繼續(xù)過斷點 來到attachToClass


    截屏2020-10-23 下午3.54.36.png
  • 將下面斷點打開 并運行 發(fā)現(xiàn)并沒有調用 attachCategories 中斷


    截屏2020-10-23 下午3.58.46.png

    總結: 非懶加載類 + 懶加載分類 map_image -> _read_images() -> realizeClassWithoutSwift -> methodizeClass ->attachToClass ->結束

3.懶加載類 + 懶加載分類

  • 下面將主類和分類里所有的load方法全部去掉 使其變?yōu)樗^的懶加載 運行 來到 realizeClassWithoutSwift


    截屏2020-10-23 下午4.04.30.png

    發(fā)現(xiàn)此時的 realizeClassWithoutSwift 是由消息慢速查找流程里的lookUpImpOrForward掉起的。這說明在第一次消息 調用時候加載數(shù)據(jù)

  • 我們繼續(xù)向下走 來到methodizeClass 方法


    截屏2020-10-23 下午4.11.13.png
  • 繼續(xù)向下走 來到attachToClass 方法


    截屏2020-10-23 下午4.12.39.png
  • 打開下圖所示斷點 看是否可以進去調用 attachCategories


    截屏2020-10-23 下午4.14.27.png
  • 發(fā)現(xiàn)并未進去 此時運行完畢

總結流程: lookUpImpOrForward -> realizeClassMaybeSwiftMaybeRelock ->realizeClassWithoutSwift->methodizeClass->走完

4.懶加載類 + 非懶加載分類 (經(jīng)測試 一個類擁有多個分類的情況下只要有大于等于兩個分類實現(xiàn)load就會走下面流程)

  • 下面將主類去掉 load 嵌削,分類全部加上load 我們再次分析
    運行發(fā)現(xiàn)奔潰 去掉 針對性代碼的元類判斷 我們根據(jù)斷點打印查看當前是否為 LGPerson


    截屏2020-10-23 下午4.27.26.png
  • 繼續(xù)運行 來到 realizeClassWithoutSwift


    截屏2020-10-23 下午4.29.32.png

    我們看調用棧 realizeClassWithoutSwift 是由 load_images發(fā)起的

  • 繼續(xù)運行來到 methodizeClass


    截屏2020-10-23 下午4.34.27.png
  • 繼續(xù)運行來到 attachToClass


    截屏2020-10-23 下午4.36.45.png
  • 打開下面斷點看其是否可以進去


    截屏2020-10-23 下午4.38.22.png
  • 繼續(xù)運行 它進來了


    截屏2020-10-23 下午4.39.34.png

*繼續(xù)過斷點 來到了 attachCategories


截屏2020-10-23 下午4.40.52.png
  • 繼續(xù)向下走


    截屏2020-10-23 下午4.43.31.png

    (1) .此時 cats_count = 2 因為兩個分類 (還記得 非懶加載類+非懶加載分類 時 cats_count是=1 而是 調用了兩遍 attachCategories方法毛好,也就是 調用一次 初始化一個64位的棧 并將方法 分類方法存入此64位的最后一位)
    (2) .此時 for循環(huán)2遍 拿到 兩個分類的 mlist 存入 mlists[64 - ++mcount ] 先進來的放在最后面 第二次進來的放在倒數(shù)第二未
    (3).分類方法排序prepareMethodLists
    (4). 通過attachLists方法 將mlists插入 rwe的方法列表

總結

  1. 懶加載類 + 非懶加載分類 調用 load_image函數(shù)的回調 -> prepare_load_methods ->realizeClassWithoutSwift ->methodizeClass -> attachToClass -> 并進入到 分類附加方法里 調用->attachCategories -> for循環(huán) 分類個數(shù)次數(shù) ; 分類方法mlist 存入 mlists[64 - ++mcount ] 先進來的放在最后面 第二次進來的放在倒數(shù)第二 -> 1.將mlists方法 序列化 ;2.通過attachLists算法將 分類的方法 貼到rwe之中 -> realizeClassWithoutSwift 判斷是否實現(xiàn)了cls實現(xiàn)返回 進入 main函數(shù)

懶加載類 + 非懶加載分類 + 懶加載分類(這種情況多個分類的情況下 有且只有一個分類為非懶加載才會走下面)

這種情況當由主類沒有實現(xiàn)load 分類 兩個其中的一個實現(xiàn)load 另一個不實現(xiàn)

  • 運行發(fā)現(xiàn)斷到realizeClassWithoutSwift是由 map_images掉起的


    截屏2020-10-23 下午5.23.48.png
  • 過斷點來到 methodizeClass


    截屏2020-10-23 下午5.26.35.png
  • 過斷點來到 attachToClass


    截屏2020-10-23 下午5.27.29.png
  • 繼續(xù)向下過斷點 看是否會進入到下邊


    截屏2020-10-23 下午5.28.41.png

*繼續(xù)向下過斷點 發(fā)現(xiàn)并未進入到 下方 attachCategories 取消斷點繼續(xù)運行 進入到了main

截屏2020-10-23 下午5.32.53.png

總結:懶加載類 + 非懶加載分類 + 懶加載分類 流程 map_images -> realizeClassWithoutSwift -> methodizeClass -> attachToClass ->進入main并未發(fā)現(xiàn) attachCategories的調用

最后總結

我們將這幾種情況的調用流程拿出來
1.非懶加載類 + 非懶加載分類
map_image -> _read_images() -> realizeClassWithoutSwift -> methodizeClass
load_image -> loadAllCategories ->load_categories_nolock -> attachCategories
2.非懶加載類 + 懶加載分類
map_image -> _read_images() -> realizeClassWithoutSwift -> methodizeClass
3.懶加載類 + 懶加載分類
lookUpImpOrForward -> realizeClassMaybeSwiftMaybeRelock ->realizeClassWithoutSwift->methodizeClass
4.懶加載類 + 非懶加載分類(多個分類大于等于兩個實現(xiàn)load流程)
load_image -> prepare_load_methods ->realizeClassWithoutSwift ->methodizeClass -> attachToClass ->attachCategories
5.懶加載類 + 非懶加載分類 + 懶加載分類(多個分類有且只有一個分類實現(xiàn)load)
map_images ->_read_images()-> realizeClassWithoutSwift -> methodizeClass

可見load的非必須不要隨意用 肌访,因為 在main函數(shù)之前會做很多很多事情。


截屏2020-10-23 下午5.43.43.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末艇劫,一起剝皮案震驚了整個濱河市吼驶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖蟹演,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件风钻,死亡現(xiàn)場離奇詭異,居然都是意外死亡酒请,警方通過查閱死者的電腦和手機骡技,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羞反,“玉大人布朦,你說我怎么就攤上這事≈绱埃” “怎么了是趴?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長澄惊。 經(jīng)常有香客問我右遭,道長,這世上最難降的妖魔是什么缤削? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吹榴,結果婚禮上亭敢,老公的妹妹穿的比我還像新娘。我一直安慰自己图筹,他們只是感情好帅刀,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著远剩,像睡著了一般扣溺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓜晤,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天锥余,我揣著相機與錄音,去河邊找鬼痢掠。 笑死驱犹,一個胖子當著我的面吹牛,可吹牛的內容都是我干的足画。 我是一名探鬼主播雄驹,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼淹辞!你這毒婦竟也來了医舆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔬将,沒想到半個月后爷速,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡娃胆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年遍希,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片里烦。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡凿蒜,死狀恐怖,靈堂內的尸體忽然破棺而出胁黑,到底是詐尸還是另有隱情,我是刑警寧澤丧蘸,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站力喷,受9級特大地震影響刽漂,放射性物質發(fā)生泄漏弟孟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一拂募、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陈症,春花似錦、人聲如沸录肯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至潘靖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卦溢,已是汗流浹背糊余。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工秀又, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贬芥。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓吐辙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蘸劈。 傳聞我的和親對象是個殘疾皇子昏苏,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355