分類的基礎知識可以看這篇Category博客
1、Category的實現原理或者本質 ?
- Category編譯之后的底層結構是struct category_t,里面存儲著分類的對象方法、類方法、屬性、協議信息
- 在程序運行的時候,runtime會將Category的數據,合并到類信息中(類對象、元類對象中)
2、Category(分類、類別)和Class Extension(擴展、延展、匿名分類)的區別是什么?
- Class Extension在編譯的時候,它的數據就已經包含在類信息中
- Category是在運行時,才會將數據合并到類信息中
- Class Extension可以添加實例變量,而Category不可以。
- Class Extension和Category都可以添加屬性,但是Category的屬性不能生成成員變量和getter、setter方法的實現。
3、Category中有load方法嗎?load方法是什么時候調用的?load 方法能繼承嗎?
- Category中有load方法
- load方法在runtime加載類、分類的時候調用
- load方法可以繼承,但一般情況下不會主動去調用load方法,都是讓系統自己調用
4、Category的加載處理過程是什么?
- 通過Runtime加載某個類的所有Category數據
- 把所有Category的方法、屬性、協議數據,合并到一個大數組中
后面參與編譯的Category數據,會在數組的前面 - 將合并后的分類數據(方法、屬性、協議),插入到類原來數據的前面
5、Category的+load方法調用順序是什么?
- +load方法會在runtime加載類、分類時調用
- 每個類、分類的+load,在程序運行過程中只調用一次
- 調用順序
- 先調用類的+load,按照編譯先后順序調用(先編譯,先調用),調用子類的+load之前會先調用父類的+load。
- 再調用分類的+load,按照編譯先后順序調用(先編譯,先調用)。
6、+initialize方法什么時候會被調用以及調用順序是什么?
- +initialize方法會在類第一次接收到消息時調用
- 調用順序
- 調用父類的+initialize方法的前提是 父類沒有被初始化過,也就是沒有調用過+initialize方法
- 先調用父類的+initialize,再調用子類的+initialize
- (先初始化父類,再初始化子類,每個類只會初始化1次)
- 如果有分類則先會調用分類的父類的+initialize方法,再調用后編譯的分類的+initialize方法
7、+initialize方法與+load方法在實際開發中有什么用?
- 當我們想在一個類加載一個內存的時候做一些事情,那么就把想做的事情寫在+load方法里面
- 如果想在一個類第一次使用的時候,那么就把想做的事情寫在+ initialize方法里面
8、load、initialize方法的區別什么?
- 8.1、調用方式
- load是根據函數地址直接調用(找到對應的方法地址,也就是那塊內存進行調用的)
- initialize是通過objc_msgSend(消息發送機制)進行調用的
- 8.2、調用時刻
- load是runtime加載類、分類的時候調用(只會調用1次)
- initialize是類第一次接收到消息時調用,每個類只會initialize一次(父類的initialize方法可能會被調用多次)
9、load、initialize方法調用的順序?
- 9.1、load
- 先調用類的load方法
- 先編譯的類,優先調用load
- 調用子類的load方法之前,會先調用父類的load方法
- 再調用分類的load方法
- 先編譯的分類優先調用load方法
- 先調用類的load方法
- 9.2、initialize
- 先初始化父類
- 再初始化子類(可能最終調用的是父類:因為如果子類沒有實現+initialize,會調用父類的+initialize(所以父類的+initialize可能會被調用多次,如果分類實現了+initialize,就覆蓋類本身的+initialize調用)
10、Category能否添加成員變量?如果可以,如何給Category添加成員變量
- 不能直接給Category添加成員變量,但是可以間接實現Category 有成員變量的效果(間接添加方式看下一篇:關聯對象)