- category 官方文檔中有如下描述
Rather than creating an entirely new class to provide minor additional capabilities over an existing class, it’s possible to define a category to add custom behavior to an existing class. You can use a category to add methods to any class, including classes for which you don’t have the original implementation source code, such as framework classes like NSString.
文檔中說明,category并不是為已經(jīng)存在的類創(chuàng)建一個新類提供一些小的附加功能,而是定義一個category去添加自定義行為,文檔中還說明了,在沒有已經(jīng)存在的類實現(xiàn)源碼,想要擴(kuò)展類的選擇的方式。
- extension 官方文檔有如下描述
If you do have the original source code for a class, you can use a class extension to add new properties, or modify the attributes of existing properties. Class extensions are commonly used to hide private behavior for use either within a single source code file, or within the private implementation of a custom framewor
文檔中說明,如果你有一個類的源碼,那么你可以添加一個extension,添加屬性、修改屬性、添加方法,那么作用是影藏私有屬性和方法,可以是一個單獨的.h文件也可以是在一個私有實現(xiàn)文件里。
category extension總結(jié):
category:1、為了在沒有實現(xiàn)源碼的基礎(chǔ)上,為已有類添加方法
2、創(chuàng)建為單獨的.h 和.m 文件,聲明的方法可以不給予實現(xiàn),但是一旦調(diào)用到則會發(fā)生crash
3、只能為已經(jīng)存在的類添加方法,不能直接添加屬性(添加屬性會生成setter。getter的聲明,但是不會生成實例變量和setter、getter方法的實現(xiàn),可通過runtime 動態(tài)綁定對象實現(xiàn)添加方法)
4、 categroy 和本類中同時實現(xiàn)同名函數(shù),優(yōu)先調(diào)用category中的方法
5.多個category中實現(xiàn)同名函數(shù),調(diào)用取決于編譯順序,最后一個編譯的被調(diào)用
6.運行期決議extension(又稱之為匿名的category):1、有源碼的基礎(chǔ)上,為類添加私有屬性和方法
2、可以將其生成一個單獨.h文件,也可以將其放在類的實現(xiàn)文件里,聲明的方法必須實現(xiàn),否則編譯器會報錯
3、可以添加屬性和方法,但是屬性和方法是私有的
4、編譯期決議,屬于類的一部分
使用category的好處
1.為無實現(xiàn)源碼的已有類添加方法(如系統(tǒng)框架中的類)
2.不同的功能組織到不同的category
3.減少單個文件體積
4.公開私有方法
5.多個開發(fā)者共同完成一個類
7.模擬多繼承
為什么category 不能添加實例變量
1、category 本身結(jié)構(gòu)不包括ivars存儲鏈表,所以先天不具備合成實例變量的條件
2、類的內(nèi)存布局在編譯時期已經(jīng)確定,category是運行時期才加載進(jìn)內(nèi)存的,所以不具備增加實例變量的條件
為什么使用objc_setAssociation可以添加實例變量
事實上關(guān)聯(lián)的對象并不是直接存儲于類結(jié)構(gòu)里的,在AssociationsManager里的靜態(tài)AssociationsHashMap存儲的是以對象的指針地址作為key的map,而其value則是一個與這個對象關(guān)聯(lián)的AssociationsHashMap,這個map存儲的是關(guān)聯(lián)的kv對。也就是說事實上就是將關(guān)聯(lián)的對象存在了這個map中,并不是直接添加到ivars列表里的,所以關(guān)聯(lián)對象并不是給對象添加實例變量的過程,也側(cè)面證實了在運行時期,類的內(nèi)存布局已經(jīng)確定,從而不能添加實例變量。
以上總結(jié)參考文檔 美團(tuán)點評-深入了解Objective-C:category很好的文章,值得深入研究