咱們在上一篇iOS底層原理之類的加載中探索了關於類的加載
,在結尾部分咱們也注意到了處理分類的代碼,此次咱們研究下分類的加載。markdown
研究分類的加載,咱們先看下分類的本質。函數
咱們在源碼中搜索category_t
,搜索結果以下從上面咱們能夠獲得分類的本質是category_t
結構體,結構體裏面有name
、cls
、實例方法列表
、類方法列表
、協議列表
、屬性列表
、類屬性列表
、元類
等信息,其中正由於分類中有屬性列表
,因此分類才能夠動態添加 屬性
(分類只能聲明屬性,因爲沒有set、get方法,因此須要動態添加
)。post
咱們以LGPerson
爲主類,咱們添加LGPerson+LGA
和LGPerson+LGB
兩個分類。 咱們從上一篇類的加載中得知最終會經過realizeClassWithoutSwift
函數將類的信息關聯起來,而realizeClassWithoutSwift
函數經過methodizeClass
函數來處理分類。spa
methodizeClass
函數分析從methodizeClass
函數中咱們能夠看到最終是經過attachToClass
函數來將分類
添加到主類
上的。3d
attachToClass
函數咱們查看attachToClass
函數代碼從中能夠看到attachToClass
函數最終又調用了attachCategories
函數code
attachCategories
函數這個函數裏面處理了分類的方法、屬性、協議等。orm
attachCategories
函數中的LGPerson
判斷部分,運行代碼到斷點位置,打印堆棧信息經過上圖咱們能夠發現實際上分類加載反推路徑
爲attachCategoriyes
-> load_categories_nolock
(執行兩次) -> loadAllCategories
-> load_images
主類跟分類混合加載主要區分在是不是懶加載類,便是否實現了+load
函數get
咱們在main函數中打下斷點,如圖所示咱們發現此時僅僅執行了readClsss
函數,經過咱們前面dyld與objc的關聯
咱們知道,這個readClass
函數在編譯階段就會執行,所以得知此時並無加載類和其分類
。咱們繼續執行代碼到NSLog處,此時咱們發現已經加載了類和其分類
,所以咱們能夠總結出來:懶加載類與懶加載分類混合,加載實際推遲到第一次消息轉發時,即本文中的[LGPerson alloc]時
源碼
仍是同懶加載類與懶加載分類混合
分析相同,從圖中咱們發現還有執行[LGPerson alloc]
時,類已經被加載了,即在編譯階段
就已經被加載了it
從上圖中咱們得知也是在編譯階段
加載了,只是在attachToClass
函數中執行了兩次load_categories_nolock
函數
從上圖中得知懶加載類與分懶加載分類混合時,會迫使主類在編譯階段加載