自己做筆錄 用來后來回顧跑杭。嚷那。
(一) Category
1、什么是category
category是objective-C 2.0之后添加的語言特性压真,別人口中的分類娩嚼、類別其實都是指category。category的主要作用是為已經(jīng)存在的類添加方法滴肿,除此之外岳悟,Apple還推薦了category的另外兩個使用場景。
可以把類的實現(xiàn)分開在幾個不同的文件里面泼差。這樣做有幾個顯而易見的好處贵少。
·可以減少單個文件的體積
·可以把不同的功能組織到不同的category里
·可以由多個開發(fā)者共同完成一個類
·可以按需加載想要的category
·聲明私有方法
apple的sdk中就大面積的使用了category這一特性。比如UIKit的UIview堆缘。apple把不同的功能API進行分類滔灶,這些分類包括UIViewGeometry、UIViewHierarchy吼肥、UIViewRendering等录平。
不過除了apple推薦的使用場景,廣大開發(fā)者腦洞大開缀皱,還衍生出了category的其他幾個使用場景:
· 模擬多繼承(另外可以墨跡多繼承的還有protocol)
· 把framework的私有方法公開
2斗这、category特點
· category只能給某個已有的類擴充方法,不能擴充成員變量啤斗。
· category中也可以添加屬性表箭,只不過@property只會生成setter和getter的聲明,不會生成setter和getter的實現(xiàn)以及成員變量钮莲。
· 如果category中的方法和類中原有方法同名免钻,運行時會優(yōu)先調(diào)用category中的方法。也就是臂痕,category中的方法會覆蓋原有的方法伯襟。
· 如果多個category中存在同名的方法,運行時到底調(diào)用那個方法由編譯器決定握童,最后一個參與編譯的方法會被調(diào)用姆怪。
3、調(diào)用優(yōu)先級
分類(category)>本類>父類。即:優(yōu)先調(diào)用category中的方法稽揭,然后調(diào)用本類方法俺附,最后調(diào)用父類方法。
注:category是在運行時加載的溪掀,不是在編譯時事镣。
4、為什么category不能添加成員變量揪胃?
Objective-C類由Class類型來表示的璃哟,它實際上是一個指向objc-class結構體的指針。它的定義如下:
typedef struct objc_class *Class;
objc_class結構體的定義如下:
super_class :父類
name:類名
version:類的版本信息喊递,默認為0
info:類信息随闪,供運行期使用的一些位標識
instance_size:該類的實例變量大小
ivars:該類的成員變量鏈表
methodLists:方法定義的鏈表
cache:方法緩存
protocols:協(xié)議鏈表
在上面的objc_class結構體中,ivars是objc_ivar_list(成員變量列表)指針骚勘;methodLists是指向objc_method_list指針的指針铐伴。在runtime中,objc_class結構體大小是固定的俏讹,不可能往這個結構體中添加數(shù)據(jù)当宴,只能修改。所以ivars指向的是一個固定區(qū)域泽疆,只能修改成員變量值户矢,不能增加成員變量個數(shù)。methodList是一個二維數(shù)組于微,所以可以修改*methodLists的值來增加成員方法逗嫡,雖然沒辦法擴展methodLists指向的內(nèi)存區(qū)域,卻可以改變這個內(nèi)存區(qū)域的值(存儲的是指針)株依。因此,可以動態(tài)添加方法延窜,不能添加成員變量恋腕。
5、category中能添加屬性么逆瑞?
category不能添加成員變量荠藤,那到底能不能添加屬性呢
typedef struct category_t {
const char *name; //類的名字
classref_t cls; //類
//category中所有給類添加的實例方法的列表
struct method_list_t *instanceMethods;
//category中所有添加的類方法的列表
struct method_list_t *classMethods;
//category實現(xiàn)的所有協(xié)議的列表
struct protocol_list_t *protocols;
//category中添加的所有屬性
struct property_list_t *instanceProperties;
} category_t;
上面是category的結構體
從category的定義也可以看出來category的可以為(可以添加實類放法,類方法获高,甚至可以實現(xiàn)協(xié)議哈肖,添加屬性)和不可為(無法添加實類變量)。
實際上念秧,category是允許添加屬性的淤井,同樣可以使用@property,但是不能生成變量,也不能生成添加屬性的getter和setter方法的實現(xiàn)币狠,所以盡管添加了屬性游两,也無法使用點語法調(diào)用getter和setter方法。但是可以使用runtime去實現(xiàn)category為已有的類添加新的屬性并生產(chǎn)getter和setter方法漩绵。
案例
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, _cmd);
}
需要注意:
1贱案、category的方法沒有“完全替換掉”原來類已經(jīng)有的方法,也就是說如果category和原來的類都有methodA止吐,那么category附加完成之后宝踪,類的方法列表會有兩個methodA。
2碍扔、category的方法被放到新方法列表的前面瘩燥,而原來類的方法被放到新方法列表的后面,這也就是我們常說的category的方法會“覆蓋”掉原來類的同名方法蕴忆,這是因為運行時在查找放到的時候是順著方法列表的順序查找的颤芬,它只要已找到對應名字的方法,就會罷休套鹅。
(二)Extension
1站蝠、什么是extension
extension是被開發(fā)者稱為擴展、延展卓鹿、匿名分類菱魔。extension看起來想一個匿名的category,但是extension和category幾乎完全是兩個東西吟孙。和category不同的是extension不但可以聲明方法澜倦,還可以聲明屬性、成員變量杰妓。extension一般用于聲明私有方法藻治,私有屬性,私有成員變量巷挥。
2桩卵、extension的存在形式
category是擁有.h文件和.m文件的東西。但是extension不然倍宾,extension只存在于一個.h文件中雏节,或者extension只能寄生于一個類的.m文件中。比如高职,viewController.m文件中通常寄生這么個東西钩乍,其實這就是一個extension:
@interface ViewController ()
@end
注意:extension常用的形式并不是以一個單獨的.h文件存在,而是寄生在類的.m文件中怔锌。
(三)category和extension的區(qū)別
就category和extension的區(qū)別來看寥粹,我們可以推導出一個明顯的事實变过,extension可以添加實例變量,而category是無法添加實例變量的(因為在運行期排作,對象的內(nèi)存布局已經(jīng)確定牵啦,如果添加實例變量就會破壞類的內(nèi)部布局,這對編譯型語言來說是災難性的)妄痪。
· extension在編譯期決議哈雏,它是類的一部分,但是category則完全不一樣衫生,它是在運行期決議的裳瘪。extension在編譯期和頭文件里的@interface以及實現(xiàn)文件里的@implement一起形成一個完整的類,它罪针、extension伴隨類的產(chǎn)生而產(chǎn)生彭羹,隨之一起消亡。
· extension一般用來隱藏類的私有信息泪酱,你不必須有一個類的源碼才能為一個類添加extension派殷,所以你無法為系統(tǒng)的類比如NSString添加extension,除非創(chuàng)建子類添加extension墓阀。而category不需要有類的源碼毡惜,我們可以給系統(tǒng)提供的類添加category。
· extension可以添加實例變量斯撮,而category不可以经伙。
· extension和category都可以添加屬性,但是category的屬性不能生成成員變量和getter勿锅、settet方法的實現(xiàn)帕膜。
本文拷貝http://www.code4app.com/blog-866962-1115.html
為了以后方便瀏覽 特地自己做收藏。