談?wù)凜ategory

一、作用

  • 減少單個(gè)文件體積,把不同功能整合到不同的Category中;
  • 可以按需加載;
  • 聲明私有方法;
  • 把framework的私有方法公開;
這是Category數(shù)據(jù)結(jié)構(gòu)

struct category_t {
    const char *name;   / /分類名
    classref_t cls;           / /分類所屬類的類名
    struct method_list_t *instanceMethods;   / /實(shí)例方法列表
    struct method_list_t *classMethods;        / /類方法列表
    struct protocol_list_t *protocols;              / /分類所實(shí)現(xiàn)協(xié)議列表
    struct property_list_t *instanceProperties;    / /實(shí)例屬性列表(可以添加屬性,但是不能添加實(shí)例變量,不要混淆實(shí)例變量和屬性)
    // 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)識(shí)),以及方法_method_list_t

分類編譯成結(jié)構(gòu)體.png
_method_list_t結(jié)構(gòu)體詳細(xì)內(nèi)容.png
所有分類都存儲(chǔ)到_ _objc_catlist字段.png

運(yùn)行期:加載分類,首先了解如下

  • dyld是蘋果的動(dòng)態(tài)加載器,用來加載 image(注意這里 image 不是指圖片,而是 Mach-O 格式的二進(jìn)制文件)。
  • 當(dāng)程序啟動(dòng)時(shí),系統(tǒng)內(nèi)核首先會(huì)加載 dyld , 而 dyld 會(huì)將我們 APP 所依賴的各種庫加載到內(nèi)存空間中,其中就包括 libobjc 庫(OC和runtime), 這些工作,是在 APP 的 main 函數(shù)執(zhí)行前完成的。
  • objc_init 是Object-C runtime 的入口函數(shù),在這里面主要功能是讀取 Mach-O 文件 OC 對(duì)應(yīng)的 Segment seciton ,并根據(jù)其中的數(shù)據(jù)代碼信息,完成為 OC 的內(nèi)存布局,以及初始化 runtime 相關(guān)的數(shù)據(jù)結(jié)構(gòu)。
    image.png
    objc初始化.png
    map_image-通過之前的標(biāo)識(shí)
    _objc_catlist加載到當(dāng)前原類,把類和分類建立關(guān)聯(lián),將分類里的方法或者屬性添加到原類,通過remethodizeClass(修改method_list的結(jié)構(gòu))布局重新排列,重點(diǎn)方法:
    image.png
    image.png
    下圖用memmove和memcpy都可以
    image.png
    但是這里的話,用memmove會(huì)更安全(首先拷貝的時(shí)候會(huì)一個(gè)一個(gè)拷貝,拷貝前兩個(gè)沒有問題,當(dāng)拷貝第三個(gè)的時(shí)候,值可能已經(jīng)變了,因?yàn)榭截惖谝粋€(gè)的時(shí)候已經(jīng)放在了第三的位置,所以可能會(huì)出現(xiàn)問題)
    image.png
關(guān)聯(lián)對(duì)象

AssociationsManager管理hashMap,hashMap管理AssociationMap,屬性最終存儲(chǔ)在ObjcAssociation中
image.png
image.png

那我們關(guān)聯(lián)的對(duì)象是什么時(shí)候釋放的?是原對(duì)象銷毀的時(shí)候
image.png
load方法探索

調(diào)用規(guī)則

1.一個(gè)類的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
最終得到存放類和分類的兩個(gè)容器;

call_load_methods:先調(diào)用類容器 loadable_classes 后調(diào)用loadable_category(與上面類和分類load調(diào)用順序就呼應(yīng)上了)
image.png
Category和extension(擴(kuò)展)

1.都可以添加屬性、方法,但是category無法生成實(shí)例變量;(原則上,category只能添加方法,可利用runtime解決setter/getter問題);
2.extension在編譯時(shí)添加到類,category在運(yùn)行時(shí)添加到類(所以category中的方法沒實(shí)現(xiàn),編譯器沒有警告--另外編譯期對(duì)象內(nèi)存布局已經(jīng)確定,在運(yùn)行期添加變量,會(huì)破壞布局);
3.定義在 .m 文件中的類擴(kuò)展方法為私有的,定義在 .h 文件(頭文件)中的類擴(kuò)展方法為公有的。

總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,663評(píng)論 1 32
  • 開篇 在平時(shí)的項(xiàng)目中時(shí)??梢杂玫紺ategory,在研究別人的代碼時(shí)遇見Category和Extension也是一...
    夜3033閱讀 2,976評(píng)論 4 15
  • 面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài) OC內(nèi)存管理 _strong 引用計(jì)數(shù)器來控制對(duì)象的生命周期。 _weak...
    運(yùn)氣不夠技術(shù)湊閱讀 1,222評(píng)論 0 10
  • 隨不經(jīng)意觸碰 擦起火花 穿過你深色衣裳 過你深色長(zhǎng)發(fā) 抵你溫潤(rùn)臉頰 此刻我心如 時(shí)雨恰逢江南 恰一路風(fēng)華 粉黛正描...
    納蘭小白閱讀 344評(píng)論 1 11
  • 我以為自己足夠勇敢 傷口裂開 鮮血會(huì)燃燒出玫瑰 然后送到情人的手上 我以為自己足夠虔誠 脊樑斷裂 憤怒會(huì)支撐起寰宇...
    風(fēng)蕭然閱讀 197評(píng)論 0 1

友情鏈接更多精彩內(nèi)容