一茉贡、作用
- 減少單個文件體積塞栅,把不同功能整合到不同的Category中;
- 可以按需加載腔丧;
- 聲明私有方法放椰;
- 把framework的私有方法公開;
這是Category數(shù)據(jù)結(jié)構(gòu)
struct category_t {
const char *name; / /分類名
classref_t cls; / /分類所屬類的類名
struct method_list_t *instanceMethods; / /實例方法列表
struct method_list_t *classMethods; / /類方法列表
struct protocol_list_t *protocols; / /分類所實現(xiàn)協(xié)議列表
struct property_list_t *instanceProperties; / /實例屬性列表(可以添加屬性愉粤,但是不能添加實例變量砾医,不要混淆實例變量和屬性)
// Fields below this point are not always present on disk.
struct property_list_t *_classProperties; / /類屬性
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
Category底層原理探索
編譯期:存放到mach-o可執(zhí)行文件('_ DATA, _objc_const'標(biāo)識),以及方法_method_list_t
分類編譯成結(jié)構(gòu)體.png
_method_list_t結(jié)構(gòu)體詳細內(nèi)容.png
所有分類都存儲到_ _objc_catlist字段.png
運行期:加載分類,首先了解如下
- dyld是蘋果的動態(tài)加載器衣厘,用來加載 image(注意這里 image 不是指圖片如蚜,而是 Mach-O 格式的二進制文件)。
- 當(dāng)程序啟動時影暴,系統(tǒng)內(nèi)核首先會加載 dyld 错邦, 而 dyld 會將我們 APP 所依賴的各種庫加載到內(nèi)存空間中,其中就包括 libobjc 庫(OC和runtime), 這些工作型宙,是在 APP 的 main 函數(shù)執(zhí)行前完成的撬呢。
- objc_init 是Object-C runtime 的入口函數(shù),在這里面主要功能是讀取 Mach-O 文件 OC 對應(yīng)的 Segment seciton 妆兑,并根據(jù)其中的數(shù)據(jù)代碼信息魂拦,完成為 OC 的內(nèi)存布局,以及初始化 runtime 相關(guān)的數(shù)據(jù)結(jié)構(gòu)搁嗓。
image.pngmap_image-通過之前的標(biāo)識 _objc_catlist加載到當(dāng)前原類芯勘,把類和分類建立關(guān)聯(lián),將分類里的方法或者屬性添加到原類腺逛,通過remethodizeClass(修改method_list的結(jié)構(gòu))布局重新排列荷愕,重點方法:objc初始化.pngimage.png下圖用memmove和memcpy都可以image.png但是這里的話,用memmove會更安全(首先拷貝的時候會一個一個拷貝屉来,拷貝前兩個沒有問題路翻,當(dāng)拷貝第三個的時候,值可能已經(jīng)變了茄靠,因為拷貝第一個的時候已經(jīng)放在了第三的位置茂契,所以可能會出現(xiàn)問題)image.pngimage.png
關(guān)聯(lián)對象
AssociationsManager管理hashMap,hashMap管理AssociationMap慨绳,屬性最終存儲在ObjcAssociation中image.png那我們關(guān)聯(lián)的對象是什么時候釋放的掉冶?是原對象銷毀的時候image.pngimage.png
load方法探索
調(diào)用規(guī)則
1.一個類的load方法在所有父類load方法調(diào)用之后調(diào)用真竖;
2.分類的load方法在當(dāng)前類的load方法調(diào)用之后調(diào)用;(這里不分父類的分類和子類的分類厌小,是所有分類)
3.分類load的調(diào)用順序和編譯順序有關(guān)恢共;
load方法調(diào)用(load_images)
prpare_load_methods:
從Macho文件加載類的列表,調(diào)整類的順序
最終得到存放類和分類的兩個容器璧亚;image.png
call_load_methods:先調(diào)用類容器 loadable_classes 后調(diào)用loadable_category(與上面類和分類load調(diào)用順序就呼應(yīng)上了)image.png
Category和extension(擴展)
1.都可以添加屬性讨韭、方法,但是category無法生成實例變量;(
原則上癣蟋,category只能添加方法透硝,可利用runtime解決setter/getter問題
);
2.extension在編譯時
添加到類疯搅,category在運行時
添加到類(所以category中的方法沒實現(xiàn)濒生,編譯器沒有警告--另外編譯期對象內(nèi)存布局已經(jīng)確定,在運行期添加變量幔欧,會破壞布局)罪治;
3.定義在 .m 文件中的類擴展方法為私有的,定義在 .h 文件(頭文件)中的類擴展方法為公有的礁蔗。總結(jié)