Category詳解

1.概念:Category是Objective-C 2.0 之后添加的語言特性,它可以為已經(jīng)存在的類添加方法

2.作用:

2.1:可以減少單個文件的體積

2.2.可以把不同的功能組織到不同的 Category 中

2.3.可以按需加載

2.4.聲明私有方法

2.5.把 framework 的私有方法公開

3.源碼:源碼鏈接:https://github.com/RetVal/objc-runtime

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é)議

? ? 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);

};

4.Category和extension(擴展)的區(qū)別

4.1.extension:

類的一部分

編譯時期決定

隱藏類的私有屬性

對象的內(nèi)存布局已確定

4.2.Category:

運行時期

不能添加變量

5.category從編譯到運行時期的過程

5.1.編譯時期:創(chuàng)建一個category,通過命令:clang -rewirte-objc category.m,可以看到它被加載到了__DATA數(shù)據(jù)段的__objc_catlist中


5.2.運行時期調(diào)用順序:

5.2.1.dyld_start:dyld是蘋果的動態(tài)加載器,用來加載動態(tài)庫,其中包括libobjc(OC和runtime)

可以通過打符號斷點看到



5.2.2._objc_init:入口函數(shù),讀取Mach-o文件對應(yīng)的Segment section,并根據(jù)其中的數(shù)據(jù)代碼信息,完成為OC的內(nèi)存布局,以及初始化runtime相關(guān)的數(shù)據(jù)結(jié)構(gòu)

5.2.3.map_images:dyld將image(Mach-o格式的二進(jìn)制文件)加載進(jìn)內(nèi)存

5.2.4.load_images:dyld初始化image,load方法也在這個時候調(diào)用

5.2.5.umap_image:dyld將image移除內(nèi)存


5.2.6.read_image:讀取oc相關(guān)的section,通過讀取seciton段來進(jìn)行初始化


map_images_nolock函數(shù)中找到_read_images


5.2.7._getObjc2CategoryList:讀取__objc_catlist


5.2.8.addUnattachedCategoryForClass:把分類加載到類當(dāng)中


5.2.9.NXMapInsert:cats(Category)和cls(類)建立關(guān)聯(lián)

5.2.10.remethodizeClass:對當(dāng)前cls 的內(nèi)存布局進(jìn)行重新排列

5.2.11.attachCategories:把當(dāng)前的cats附加到cls中


5.2.12.prepareMethodLists:準(zhǔn)備當(dāng)前類的方法列表


5.2.13.attachLists:通過memmove和memcpy,把分類的方法添加到原來的方法列表當(dāng)中


6.總結(jié):

6.1.通過5.2.7_getObjc2CategoryList讀取__objc_catlist secition段記錄中所有的category,存放到category_t 數(shù)組中

6.2.依次讀取category_t數(shù)組

6.3.cat和cls進(jìn)行映射

6.4.通過remethodizeClass修改method_list結(jié)構(gòu),這里涉及到memove和memcpy

7.動態(tài)添加屬性

7.1.AssociationsManager中存放了一個map(AssociationsHashMap),map中的key是當(dāng)前對象地址的按位取反,value是一個迭代器,也是一個map,迭代器map中的key是自定義的標(biāo)識,value是ObjcAssociation(用戶自定義的,用來存儲當(dāng)前的關(guān)聯(lián)屬性





7.2.關(guān)聯(lián)對象的釋放是在源對象被銷毀時釋放(dealloc),通過對象的指針來釋放關(guān)聯(lián)對象,具體調(diào)用的是_object_remove_assocations中的ReleaseValue


8.load方法:

8.1.一個類的load方法在所有的父類都調(diào)用完之后調(diào)用

8.2.category的調(diào)用load方法在類的調(diào)用load方法之后調(diào)用

8.3.category之間的調(diào)用順序:通過dyld調(diào)整調(diào)用順序和編譯順序有關(guān)

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

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

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