深入淺出理解分類(lèi)(category,類(lèi)別,類(lèi)目)和類(lèi)擴(kuò)展(extension,匿名類(lèi)別)

整理資料. ??

深入淺出理解分類(lèi)(category,類(lèi)別,類(lèi)目)和類(lèi)擴(kuò)展(extension,匿名類(lèi)別)

蘋(píng)果推薦分類(lèi)的使用 ,可以如下使用:

1.給已經(jīng)存在的類(lèi)添加方法

2.把類(lèi)的實(shí)現(xiàn)分開(kāi)在幾個(gè)不同文件中

減少單個(gè)文件的體積

把不同功能組織到不同的category里

多個(gè)開(kāi)發(fā)者共同完成一個(gè)類(lèi)

按照需求加載想要的category

3.聲明私有方法

除此之外,我們還可以轉(zhuǎn)換思想,將category使用到如下地方:

4.模仿多繼承

5.把framework的私有方法分開(kāi)



分類(lèi)運(yùn)用場(chǎng)景舉例:想要收集每個(gè)頁(yè)面的啟動(dòng)時(shí)間。

問(wèn)題1:

項(xiàng)目中已經(jīng)有上百個(gè)頁(yè)面了,如果一個(gè)一個(gè)的加,浪費(fèi)時(shí)間不說(shuō),以后增加了新頁(yè)面,還需要添加方法。

解決方法:

我們可以發(fā)現(xiàn)頁(yè)面都繼承了UIViewController,想要在每個(gè)頁(yè)面都執(zhí)行的代碼,可以寫(xiě)在這些頁(yè)面的父類(lèi)中。我們可以把代碼寫(xiě)在UIViewController中。

問(wèn)題2:

UIViewController是官方類(lèi),我們只能調(diào)用期接口,并不能修改他的實(shí)現(xiàn)。

解決方法:

使用分類(lèi)(category)。

1.分類(lèi)(category)的作用

1.1作用:可以在不修改原來(lái)類(lèi)的基礎(chǔ)上,為一個(gè)類(lèi)擴(kuò)展方法。

1.2最主要的用法:給系統(tǒng)自帶的類(lèi)擴(kuò)展方法。

2.分類(lèi)中能寫(xiě)點(diǎn)啥?

2.1分類(lèi)中只能添加“方法”,不能增加成員變量。? (在runtime層面可以通過(guò)關(guān)聯(lián)對(duì)象為分類(lèi)添加成員屬性

2.2分類(lèi)中可以訪(fǎng)問(wèn)原來(lái)類(lèi)中的成員變量,但是只能訪(fǎng)問(wèn)@protect和@public形式的變量。如果想要訪(fǎng)問(wèn)本類(lèi)中的私有變量,分類(lèi)和子類(lèi)一樣,只能通過(guò)方法來(lái)訪(fǎng)問(wèn)。

2.3如果一定要在分類(lèi)中添加成員變量,可以通過(guò)getter,setter手段進(jìn)行添加,詳細(xì)以后再寫(xiě),TODO。

3.分類(lèi)的書(shū)寫(xiě)方法

假設(shè)我們有一個(gè)類(lèi),名叫Person,意義是人類(lèi)。在person類(lèi)中我們有一個(gè)方法,-(void)eat;意義是吃,因?yàn)槊總€(gè)人類(lèi)都會(huì)吃。

人類(lèi)有很多共同特點(diǎn),也有很多不同點(diǎn),比如,并不是每個(gè)人都會(huì)踢足球。這時(shí)候我寫(xiě)一個(gè)分類(lèi),給喜歡運(yùn)動(dòng)的人,這個(gè)分類(lèi)的名字叫做sport。因?yàn)槭莗erson類(lèi)的分類(lèi),你會(huì)看到生成的名字叫做Person+sport。下面讓我們來(lái)試著添加一下。

0.分類(lèi)的使用過(guò)程:聲明分類(lèi)->實(shí)現(xiàn)分類(lèi)->使用分類(lèi)?

1.在項(xiàng)目中添加類(lèi),選擇Objective-C File,在?彈出的頁(yè)面中這樣配置。

2.Person+sport.h頭文件

3.Person+sport.m文件

4.回到最開(kāi)始收集頁(yè)面啟動(dòng)時(shí)間的問(wèn)題,本類(lèi)是系統(tǒng)的類(lèi),這里是UIViewController,我們可以使用分類(lèi)擴(kuò)展他的方法,也可以重寫(xiě)他的方法,可以我需要在調(diào)用的地方加頭文件,所有子類(lèi)都寫(xiě)頭文件和直接在子類(lèi)寫(xiě)方法沒(méi)有什么區(qū)別,怎么樣可以使得不寫(xiě)頭文件,子類(lèi)就能調(diào)用我們寫(xiě)的代碼呢?

回答:

我們可以進(jìn)行方法交換Method Swizzling(這樣可以不必在調(diào)用的地方增加頭文件),從而使得在實(shí)現(xiàn)的時(shí)候調(diào)用重寫(xiě)的方法。具體實(shí)現(xiàn)以后寫(xiě)


category底層結(jié)構(gòu)

我們知道,所有OC類(lèi)和對(duì)象,在runtime層都是用struct表示的,category在runtime層使用結(jié)構(gòu)體category_t定義的,包含了如下:

name 類(lèi)名

cls 類(lèi)

instanceMethods 對(duì)象方法

classMethods 類(lèi)方法

protocols 協(xié)議列表

instanceProperties 添加的所有屬性

4.分類(lèi)的執(zhí)行優(yōu)先級(jí)、方法調(diào)用順序? category加載?

category加載

在runtime,系統(tǒng)會(huì)將包含的內(nèi)容添加如下:

把category的實(shí)力方法,協(xié)議,已經(jīng)屬性添加到類(lèi)上

把類(lèi)方法和協(xié)議添加到metaclass

分類(lèi)加載和方法調(diào)用順序

加載:先加載原類(lèi)的+load方法,再加載分類(lèi)的+load方法,若多個(gè)分類(lèi),則根據(jù)編譯順序加載

調(diào)用:先調(diào)用分類(lèi)的方法,再調(diào)用原類(lèi)的方法,分類(lèi)方法會(huì)覆蓋原類(lèi)的方法

分類(lèi)覆蓋類(lèi)的方法

如果分類(lèi)中的方法與類(lèi)的方法同名,則將會(huì)覆蓋類(lèi)的方法,實(shí)現(xiàn)原理:分類(lèi)的對(duì)象方法會(huì)添加到類(lèi)的方法列表中,分類(lèi)的方法會(huì)添加到類(lèi)的相應(yīng)方法列表中(對(duì)象方法添加到類(lèi)的方法列表,類(lèi)方法會(huì)添加到metaclass列表),而且排列順序會(huì)與原類(lèi)的同名方法排在一起,且在原類(lèi)的同名方法的前面。方法調(diào)用時(shí)會(huì)根據(jù)順序先找到第一同名方法就調(diào)用,因此會(huì)覆蓋原類(lèi)的同名方法。

4.1在本類(lèi)和分類(lèi)有相同的方法時(shí),優(yōu)先調(diào)用分類(lèi)的方法再調(diào)用本類(lèi)的方法。

4.2如果有兩個(gè)分類(lèi),他們都實(shí)現(xiàn)了相同的方法,如何判斷誰(shuí)先執(zhí)行?分類(lèi)執(zhí)行順序可以通過(guò)targets,Build Phases,Complie Source進(jìn)行調(diào)節(jié),注意執(zhí)行順序是從上到下的。(只有兩個(gè)相同方法名的分類(lèi))

5.分類(lèi)(category)和類(lèi)擴(kuò)展(extension)的關(guān)系

1.類(lèi)擴(kuò)展(extension)是category的一個(gè)特例,有時(shí)候也被稱(chēng)為匿名分類(lèi)。他的作用是為一個(gè)類(lèi)添加一些私有的成員變量和方法。

2.類(lèi)擴(kuò)展能寫(xiě)點(diǎn)啥?和分類(lèi)不同,類(lèi)擴(kuò)展即可以聲明成員變量又可以聲明方法。

3.類(lèi)擴(kuò)展聽(tīng)上去很復(fù)雜,但其實(shí)我們很早就認(rèn)識(shí)他了。你記得繼承自UIViewController的ViewController和繼承自NSObject的類(lèi)有什么不同么?

4.繼承自UIViewController的ViewController類(lèi)

5.對(duì)比看一下繼承自NSObject的類(lèi)我們會(huì)發(fā)現(xiàn)沒(méi)有上面的代碼塊

@interface?ViewController()//這就是類(lèi)擴(kuò)展的寫(xiě)法

@end

6.類(lèi)擴(kuò)展可以定義在.m文件中,這種擴(kuò)展方式中定義的變量都是私有的,也可以定義在.h文件中,這樣定義的代碼就是共有的,類(lèi)擴(kuò)展在.m文件中聲明私有方法是非常好的方式。

7.類(lèi)擴(kuò)展中添加的新方法,一定要實(shí)現(xiàn)。categorygory中沒(méi)有這種限制。


category和extension區(qū)別1

category: 類(lèi)別,分類(lèi)

專(zhuān)門(mén)用來(lái)給類(lèi)添加新的方法

不能給類(lèi)添加成員屬性,添加了成員變量,也無(wú)法取到

注意:其實(shí)可以通過(guò)runtime給分類(lèi)添加屬性

分類(lèi)中用@property定義變量,只會(huì)生成變量的getter,setter方法的聲明,不能生成方法實(shí)現(xiàn)和帶下劃線(xiàn)的成員變量。

extension:類(lèi)擴(kuò)展

可以說(shuō)成是特殊的分類(lèi),也稱(chēng)作匿名分類(lèi)

可以給類(lèi)添加成員屬性,但是是私有變量

可以給類(lèi)添加方法,也是私有方法

category和extension區(qū)別2

雖然有人說(shuō)extension是一個(gè)特殊的category,也有人將extension叫做匿名分類(lèi),但是其實(shí)兩者差別很大。

extension

在編譯器決議,是類(lèi)的一部分,在編譯器和頭文件的@interface和實(shí)現(xiàn)文件里的@implement一起形成了一個(gè)完整的類(lèi)。

伴隨著類(lèi)的產(chǎn)生而產(chǎn)生,也隨著類(lèi)的消失而消失。

extension一般用來(lái)隱藏類(lèi)的私有消息,你必須有一個(gè)類(lèi)的源碼才能添加一個(gè)類(lèi)的extension,所以對(duì)于系統(tǒng)一些類(lèi),如nsstring,就無(wú)法添加類(lèi)擴(kuò)展

category

是運(yùn)行期決議的

類(lèi)擴(kuò)展可以添加實(shí)例變量,分類(lèi)不能添加實(shí)例變量

原因:因?yàn)樵谶\(yùn)行期,對(duì)象的內(nèi)存布局已經(jīng)確定,如果添加實(shí)例變量會(huì)破壞類(lèi)的內(nèi)部布局,這對(duì)編譯性語(yǔ)言是災(zāi)難性的。

為什么Category只能為對(duì)象添加方法,卻不能添加成員變量?

Category只能為對(duì)象添加方法,卻不能添加成員變量的原因:如果可以添加成員變量,添加的成員變量沒(méi)有辦法初始化


引用資料:1 http://www.cocoachina.com/ios/20161018/17784.html

? ? ? ? ? ? ? ? ? ? ?2?Category分類(lèi)和Extension類(lèi)擴(kuò)展的詳解與區(qū)別

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

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

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