//聯(lián)系人:石虎?QQ:1224614774?昵稱:嗡嘛呢叭咪哄
一您朽、概念
1.前言
category是Objective-C?2.0之后添加的語言特性肥照,
category的主要作用是為已經(jīng)存在的類添加方法。
2.設(shè)計思想
?Objective-C 中的 Category 就是對裝飾模式的一種具體實現(xiàn)世落。它的主要作用是在不改變原有類的前提下,動態(tài)地給這個類添加一些方法。
在 Objective-C 中的具體體現(xiàn)為:實例(類)方法父泳、屬性和協(xié)議般哼。
二、使用場景
1.給現(xiàn)有的類添加方法惠窄;
2.將一個類的實現(xiàn)拆分成多個獨立的源文件;
?好處:
? a)可以減少單個文件的體積
? b)可以把不同的功能組織到不同的category里
? c)可以由多個開發(fā)者共同完成一個類
? d)可以按需加載想要的category 等等蒸眠。
3.聲明私有的方法。
三杆融、實現(xiàn)原理
1.我們不主動引入 Category 的頭文件楞卡,Category 中的方法都會被添加進主類中。我們可以通過?- performSelector:?等方式 對 Category 中的相應(yīng)方法進行調(diào)用
?a)將 Category 和它的主類(或元類)注冊到哈希表中脾歇;
?b)如果主類(或元類)已實現(xiàn)蒋腮,那么重建它的方法列表。
2.在這里分了兩種情況進行處理:Category 中的實例方法和屬性被整合到主類中藕各;而類方法則被整合到元類中(關(guān)于對象池摧、類和元類的更多細節(jié),可以參考我前面的博文《Objective-C對象模型》)激况。另外作彤,對協(xié)議的處理比較特殊,Category 中的協(xié)議被同時整合到了主類和元類中乌逐。
3.注意到宦棺,不管是哪種情況,最終都是通過調(diào)用staticvoid?remethodizeClass(Class cls)?函數(shù)來重新整理類的數(shù)據(jù)的黔帕。
四代咸、category結(jié)構(gòu)體
1.所有的OC類和對象,在runtime層都是用struct表示的成黄,category也不例外呐芥,在runtime層,category用結(jié)構(gòu)體category_t.
2.category結(jié)構(gòu)體的定義:
structcategory_t?{
constchar*name;//類的名字(name)
classref_t?cls;//類(cls)
? ? ??struct?method_list_t?*instanceMethods;?//category中所有給類添加的實例方法的列表(instanceMethods)
structmethod_list_t?*classMethods;//category中所有添加的類方法的列表(classMethods)
structprotocol_list_t?*protocols;?//category實現(xiàn)的所有協(xié)議的列表(protocols)
structproperty_list_t?*instanceProperties;//category中添加的所有屬性(instanceProperties)
};
3.從category的定義也可以看出category可以添加實例方法奋岁,類方法思瘟;可以遵守協(xié)議,添加屬性闻伶;但無法添加實例變量滨攻。
注意,在category中可以有屬性(property)蓝翰,但是該屬性只是生成了getter和setter方法的聲明光绕,并沒有產(chǎn)生對應(yīng)的實現(xiàn),更不會添加對應(yīng)的實例變量畜份。如果想為實例對象添加實例變量诞帐,可以嘗試使用關(guān)聯(lián)引用技術(shù)。
五爆雹、添加方法列表
原理圖:
1.添加方法列表的時候是后添加的在新形成的列表前部停蕉,這也是為什么在有多個category中有同名方法時愕鼓,后編譯的在調(diào)用時會“覆蓋”前面已編譯的方法。其實方法本身并沒有被覆蓋慧起,只是調(diào)用的時候是從上而下查找方法列表菇晃,當(dāng)運行時找到對應(yīng)的方法名后就去忙著調(diào)用了,并不會管后面的同名方法蚓挤。
2.關(guān)于load方法:
? 其實在上面的源碼中也可以看到,category 中對load方法的處理過并沒有什么特殊磺送。因此,可以說category 中的 load 方法跟普通方法一樣也會對主類中的 load方法造成覆蓋屈尼,只不過 runtime在自動調(diào)用主類和 category中的 load方法時是直接使用各自方法的指針進行調(diào)用的册着。所以我們感覺不到category對主類的影響。其實手動給主類發(fā)送load 消息時脾歧,調(diào)用的將會是分類中的load 方法甲捏。
六、注意項
1.Category 有一個非常容易誤用的場景鞭执,那就是用 Category 來覆寫父類或主類的方法司顿。雖然目前 Objective-C 是允許這么做的,但是這種使用場景是非常不推薦的兄纺。
2.使用?Category 來覆寫方法有很多缺點大溜,比如不能覆寫 Category 中的方法、無法調(diào)用主類中的原始實現(xiàn)等估脆,且很容易造成無法預(yù)估的行為钦奋。