Category的底層分析之initialize

2021-10-25 19:22:04 字數 1966 閱讀 1891

這篇部落格我們將圍繞這幾個問題來**initialize.

首先看我的截圖,我們先看一下initialize會不會像load一樣,runtime載入類、分類的時候就會呼叫.

還是一樣,我建立gdperson類和test1、test2分類,裡面分別呼叫了initialize方法,如下:

+initialize方法會在類第一次接收到訊息的時候呼叫

下面我們先用**驗證,比如我先給gdperson發alloc [gdperson alloc];我們看一下結果

細心的可能發現,這裡是不是和我們之前的類方法呼叫非常像,其實是一樣的,它也是通過訊息機制來傳送的類似objc_msgsend([gdperson class],@selector(initialize)),根據我們之前的知識知道,如果類和分類方法同名,優先呼叫分類的方法,而且是後編譯的先呼叫一摸一樣(大家可以自己嘗試上面的**,後面我會證明),接下來我們看一下.

如果出現繼承會怎麼樣?

我再建立乙個gdstudent的類,裡面同樣列印gdstudent+initialize,我們看看結果:

initialize呼叫的時候會優先呼叫父類的initialize,再呼叫子類的initialize,而且先初始化父類,再初始化子類,每個類只會初始化一次

+initialize有可能會呼叫多次的情況

現在我再建立gdcat的子類,繼承gdstudent,然後把gdstudent裡面的+(void)initialize刪除,我們再執行一下看看會出現什麼情況.

父類的是被呼叫了多次,也很清楚是為什麼,gdstudent在初始化的時候會呼叫+initialize,它就會來到我們之前學習的,先通過isa找到gdstudent的元類物件,在元類物件找+initialize,發現找不到,就會通過superclass找父類gdperson的元類物件,再去找發現找到了,所以就列印了2次.這裡我們又知道initialize的另外一種情況

原始碼分析

首先我們想既然是在發訊息的時候呼叫+initialize方法,所以我們去原始碼看看objc_msgsend方法有沒有介紹+initialize的情況.

(如果後面有可以看出的,我會補充上).

1.+initialize方法會在類第一次收到資訊時呼叫

2.先呼叫父類的+initialize,再呼叫子類的+initialize(先初始化父類,再初始化子類,每個類只會初始化一次)

3.如果子類沒有實現+initialize,會呼叫父類的+initialize (所以父類的+initialize 可能會被呼叫多次)

4.如果分類實現了+initialize,就會覆蓋類本身的+initialize呼叫

1.load是根據函式位址直接呼叫,initialize是通過objc_msgsend呼叫(呼叫方式上)

2.load是在runtime載入類、分類的時候呼叫(只會呼叫1次),而initialize是在第一次接收到訊息的時候呼叫,每個類只會initialize一次,父類的initialize可能被執行多次(呼叫時刻上)

3.load:先呼叫類的,呼叫子類之前會先呼叫父類,先編譯的類,優先呼叫,

然後再呼叫分類的,也是先編譯的分類優先呼叫;

initialize:先初始化父類,再初始化子類,可能是多次呼叫父類的initialize.(呼叫順序上)

Category的底層分析之load

今天我們就圍繞乙個面試題來從原始碼的角度分析答案!一 category中有load方法嗎?load方法是什麼時候呼叫的?load方法能繼承嗎?如果分類又存在繼承是如何載入load順序的呢?首先我們先看下下面的 我們先看 執行結果,再從原始碼上分析!gdperson.m檔案裡面 void load g...

Category的底層分析

簡介 category是objective c 2.0之後新增的語言特性,分類 類別其實都是指的category。category的主要作用是為已經存在的類新增方法。objective c 中的 category 就是對裝飾模式的一種具體實現。它的主要作用是在不改變原有類的前提下,動態地給這個類新增...

Objective C之Category的使用

category是oc的特有的語法 分類的宣告 inte ce classname categoryname newmethod 在類別中新增方法 不允許在類別中新增變數 end 分類的實現 implementation classname categoryname newmethod end cl...