一蛛勉、概念
1.前言
category是Objective-C?2.0之后添加的語(yǔ)言特性廷雅,
category的主要作用是為已經(jīng)存在的類添加方法届谈。
2.設(shè)計(jì)思想
?Objective-C 中的 Category 就是對(duì)裝飾模式的一種具體實(shí)現(xiàn)晓褪。它的主要作用是在不改變?cè)蓄惖那疤嵯拢瑒?dòng)態(tài)地給這個(gè)類添加一些方法扎筒。
在 Objective-C 中的具體體現(xiàn)為:實(shí)例(類)方法、屬性和協(xié)議酬姆。
二嗜桌、使用場(chǎng)景
1.給現(xiàn)有的類添加方法;
2.將一個(gè)類的實(shí)現(xiàn)拆分成多個(gè)獨(dú)立的源文件;
?好處:
? a)可以減少單個(gè)文件的體積
? b)可以把不同的功能組織到不同的category里
? c)可以由多個(gè)開(kāi)發(fā)者共同完成一個(gè)類
? d)可以按需加載想要的category 等等辞色。
3.聲明私有的方法骨宠。
三、實(shí)現(xiàn)原理
1.我們不主動(dòng)引入 Category 的頭文件,Category 中的方法都會(huì)被添加進(jìn)主類中层亿。我們可以通過(guò)?- performSelector:?等方式 對(duì) Category 中的相應(yīng)方法進(jìn)行調(diào)用
?a)將 Category 和它的主類(或元類)注冊(cè)到哈希表中桦卒;
?b)如果主類(或元類)已實(shí)現(xiàn),那么重建它的方法列表匿又。
2.在這里分了兩種情況進(jìn)行處理:Category 中的實(shí)例方法和屬性被整合到主類中方灾;而類方法則被整合到元類中(關(guān)于對(duì)象、類和元類的更多細(xì)節(jié)碌更,可以參考我前面的博文《Objective-C對(duì)象模型》)裕偿。另外,對(duì)協(xié)議的處理比較特殊痛单,Category 中的協(xié)議被同時(shí)整合到了主類和元類中嘿棘。
3.注意到,不管是哪種情況旭绒,最終都是通過(guò)調(diào)用staticvoid?remethodizeClass(Class cls)?函數(shù)來(lái)重新整理類的數(shù)據(jù)的鸟妙。
四、category結(jié)構(gòu)體
1.所有的OC類和對(duì)象挥吵,在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中所有給類添加的實(shí)例方法的列表(instanceMethods)
structmethod_list_t?*classMethods;//category中所有添加的類方法的列表(classMethods)
structprotocol_list_t?*protocols;?//category實(shí)現(xiàn)的所有協(xié)議的列表(protocols)
structproperty_list_t?*instanceProperties;//category中添加的所有屬性(instanceProperties)
};
3.從category的定義也可以看出category可以添加實(shí)例方法坪郭,類方法;可以遵守協(xié)議脉幢,添加屬性歪沃;但無(wú)法添加實(shí)例變量。
注意嫌松,在category中可以有屬性(property)沪曙,但是該屬性只是生成了getter和setter方法的聲明,并沒(méi)有產(chǎn)生對(duì)應(yīng)的實(shí)現(xiàn)萎羔,更不會(huì)添加對(duì)應(yīng)的實(shí)例變量液走。如果想為實(shí)例對(duì)象添加實(shí)例變量,可以嘗試使用關(guān)聯(lián)引用技術(shù)贾陷。
五缘眶、添加方法列表
原理圖:
1.添加方法列表的時(shí)候是后添加的在新形成的列表前部,這也是為什么在有多個(gè)category中有同名方法時(shí)髓废,后編譯的在調(diào)用時(shí)會(huì)“覆蓋”前面已編譯的方法巷懈。其實(shí)方法本身并沒(méi)有被覆蓋,只是調(diào)用的時(shí)候是從上而下查找方法列表慌洪,當(dāng)運(yùn)行時(shí)找到對(duì)應(yīng)的方法名后就去忙著調(diào)用了顶燕,并不會(huì)管后面的同名方法凑保。
2.關(guān)于load方法:
? 其實(shí)在上面的源碼中也可以看到,category 中對(duì)load方法的處理過(guò)并沒(méi)有什么特殊。因此涌攻,可以說(shuō)category 中的 load 方法跟普通方法一樣也會(huì)對(duì)主類中的 load方法造成覆蓋欧引,只不過(guò) runtime在自動(dòng)調(diào)用主類和 category中的 load方法時(shí)是直接使用各自方法的指針進(jìn)行調(diào)用的。所以我們感覺(jué)不到category對(duì)主類的影響恳谎。其實(shí)手動(dòng)給主類發(fā)送load 消息時(shí)芝此,調(diào)用的將會(huì)是分類中的load 方法。
六惠爽、注意項(xiàng)
1.Category 有一個(gè)非常容易誤用的場(chǎng)景癌蓖,那就是用 Category 來(lái)覆寫父類或主類的方法。雖然目前 Objective-C 是允許這么做的婚肆,但是這種使用場(chǎng)景是非常不推薦的租副。
2.使用?Category 來(lái)覆寫方法有很多缺點(diǎn),比如不能覆寫 Category 中的方法较性、無(wú)法調(diào)用主類中的原始實(shí)現(xiàn)等用僧,且很容易造成無(wú)法預(yù)估的行為。