整理資料. ??
深入淺出理解分類(category,類別,類目)和類擴(kuò)展(extension,匿名類別)
蘋(píng)果推薦分類的使用 ,可以如下使用:
1.給已經(jīng)存在的類添加方法
2.把類的實(shí)現(xiàn)分開(kāi)在幾個(gè)不同文件中
減少單個(gè)文件的體積
把不同功能組織到不同的category里
多個(gè)開(kāi)發(fā)者共同完成一個(gè)類
按照需求加載想要的category
3.聲明私有方法
除此之外,我們還可以轉(zhuǎn)換思想,將category使用到如下地方:
4.模仿多繼承
5.把framework的私有方法分開(kā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è)面的父類中。我們可以把代碼寫(xiě)在UIViewController中。
問(wèn)題2:
UIViewController是官方類,我們只能調(diào)用期接口,并不能修改他的實(shí)現(xiàn)。
解決方法:
使用分類(category)。
1.分類(category)的作用
1.1作用:可以在不修改原來(lái)類的基礎(chǔ)上,為一個(gè)類擴(kuò)展方法。
1.2最主要的用法:給系統(tǒng)自帶的類擴(kuò)展方法。
2.分類中能寫(xiě)點(diǎn)啥?
2.1分類中只能添加“方法”,不能增加成員變量。? (在runtime層面可以通過(guò)關(guān)聯(lián)對(duì)象為分類添加成員屬性)
2.2分類中可以訪問(wèn)原來(lái)類中的成員變量,但是只能訪問(wèn)@protect和@public形式的變量。如果想要訪問(wèn)本類中的私有變量,分類和子類一樣,只能通過(guò)方法來(lái)訪問(wèn)。
2.3如果一定要在分類中添加成員變量,可以通過(guò)getter,setter手段進(jìn)行添加,詳細(xì)以后再寫(xiě),TODO。
3.分類的書(shū)寫(xiě)方法
假設(shè)我們有一個(gè)類,名叫Person,意義是人類。在person類中我們有一個(gè)方法,-(void)eat;意義是吃,因?yàn)槊總€(gè)人類都會(huì)吃。
人類有很多共同特點(diǎn),也有很多不同點(diǎn),比如,并不是每個(gè)人都會(huì)踢足球。這時(shí)候我寫(xiě)一個(gè)分類,給喜歡運(yùn)動(dòng)的人,這個(gè)分類的名字叫做sport。因?yàn)槭莗erson類的分類,你會(huì)看到生成的名字叫做Person+sport。下面讓我們來(lái)試著添加一下。
0.分類的使用過(guò)程:聲明分類->實(shí)現(xiàn)分類->使用分類?
1.在項(xiàng)目中添加類,選擇Objective-C File,在?彈出的頁(yè)面中這樣配置。

2.Person+sport.h頭文件

3.Person+sport.m文件

4.回到最開(kāi)始收集頁(yè)面啟動(dòng)時(shí)間的問(wèn)題,本類是系統(tǒng)的類,這里是UIViewController,我們可以使用分類擴(kuò)展他的方法,也可以重寫(xiě)他的方法,可以我需要在調(diào)用的地方加頭文件,所有子類都寫(xiě)頭文件和直接在子類寫(xiě)方法沒(méi)有什么區(qū)別,怎么樣可以使得不寫(xiě)頭文件,子類就能調(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類和對(duì)象,在runtime層都是用struct表示的,category在runtime層使用結(jié)構(gòu)體category_t定義的,包含了如下:
name 類名
cls 類
instanceMethods 對(duì)象方法
classMethods 類方法
protocols 協(xié)議列表
instanceProperties 添加的所有屬性
4.分類的執(zhí)行優(yōu)先級(jí)、方法調(diào)用順序? category加載?
category加載
在runtime,系統(tǒng)會(huì)將包含的內(nèi)容添加如下:
把category的實(shí)力方法,協(xié)議,已經(jīng)屬性添加到類上
把類方法和協(xié)議添加到metaclass
分類加載和方法調(diào)用順序
加載:先加載原類的+load方法,再加載分類的+load方法,若多個(gè)分類,則根據(jù)編譯順序加載
調(diào)用:先調(diào)用分類的方法,再調(diào)用原類的方法,分類方法會(huì)覆蓋原類的方法
分類覆蓋類的方法
如果分類中的方法與類的方法同名,則將會(huì)覆蓋類的方法,實(shí)現(xiàn)原理:分類的對(duì)象方法會(huì)添加到類的方法列表中,分類的方法會(huì)添加到類的相應(yīng)方法列表中(對(duì)象方法添加到類的方法列表,類方法會(huì)添加到metaclass列表),而且排列順序會(huì)與原類的同名方法排在一起,且在原類的同名方法的前面。方法調(diào)用時(shí)會(huì)根據(jù)順序先找到第一同名方法就調(diào)用,因此會(huì)覆蓋原類的同名方法。
4.1在本類和分類有相同的方法時(shí),優(yōu)先調(diào)用分類的方法再調(diào)用本類的方法。
4.2如果有兩個(gè)分類,他們都實(shí)現(xiàn)了相同的方法,如何判斷誰(shuí)先執(zhí)行?分類執(zhí)行順序可以通過(guò)targets,Build Phases,Complie Source進(jìn)行調(diào)節(jié),注意執(zhí)行順序是從上到下的。(只有兩個(gè)相同方法名的分類)
5.分類(category)和類擴(kuò)展(extension)的關(guān)系
1.類擴(kuò)展(extension)是category的一個(gè)特例,有時(shí)候也被稱為匿名分類。他的作用是為一個(gè)類添加一些私有的成員變量和方法。
2.類擴(kuò)展能寫(xiě)點(diǎn)啥?和分類不同,類擴(kuò)展即可以聲明成員變量又可以聲明方法。
3.類擴(kuò)展聽(tīng)上去很復(fù)雜,但其實(shí)我們很早就認(rèn)識(shí)他了。你記得繼承自UIViewController的ViewController和繼承自NSObject的類有什么不同么?
4.繼承自UIViewController的ViewController類

5.對(duì)比看一下繼承自NSObject的類我們會(huì)發(fā)現(xiàn)沒(méi)有上面的代碼塊
@interface?ViewController()//這就是類擴(kuò)展的寫(xiě)法
@end
6.類擴(kuò)展可以定義在.m文件中,這種擴(kuò)展方式中定義的變量都是私有的,也可以定義在.h文件中,這樣定義的代碼就是共有的,類擴(kuò)展在.m文件中聲明私有方法是非常好的方式。
7.類擴(kuò)展中添加的新方法,一定要實(shí)現(xiàn)。categorygory中沒(méi)有這種限制。
category和extension區(qū)別1
category: 類別,分類
專門(mén)用來(lái)給類添加新的方法
不能給類添加成員屬性,添加了成員變量,也無(wú)法取到
注意:其實(shí)可以通過(guò)runtime給分類添加屬性
分類中用@property定義變量,只會(huì)生成變量的getter,setter方法的聲明,不能生成方法實(shí)現(xiàn)和帶下劃線的成員變量。
extension:類擴(kuò)展
可以說(shuō)成是特殊的分類,也稱作匿名分類
可以給類添加成員屬性,但是是私有變量
可以給類添加方法,也是私有方法
category和extension區(qū)別2
雖然有人說(shuō)extension是一個(gè)特殊的category,也有人將extension叫做匿名分類,但是其實(shí)兩者差別很大。
extension
在編譯器決議,是類的一部分,在編譯器和頭文件的@interface和實(shí)現(xiàn)文件里的@implement一起形成了一個(gè)完整的類。
伴隨著類的產(chǎn)生而產(chǎn)生,也隨著類的消失而消失。
extension一般用來(lái)隱藏類的私有消息,你必須有一個(gè)類的源碼才能添加一個(gè)類的extension,所以對(duì)于系統(tǒng)一些類,如nsstring,就無(wú)法添加類擴(kuò)展
category
是運(yùn)行期決議的
類擴(kuò)展可以添加實(shí)例變量,分類不能添加實(shí)例變量
原因:因?yàn)樵谶\(yùn)行期,對(duì)象的內(nèi)存布局已經(jīng)確定,如果添加實(shí)例變量會(huì)破壞類的內(nèi)部布局,這對(duì)編譯性語(yǔ)言是災(zāi)難性的。
為什么Category只能為對(duì)象添加方法,卻不能添加成員變量?
Category只能為對(duì)象添加方法,卻不能添加成員變量的原因:如果可以添加成員變量,添加的成員變量沒(méi)有辦法初始化
引用資料:1 http://www.cocoachina.com/ios/20161018/17784.html
? ? ? ? ? ? ? ? ? ? ?2?Category分類和Extension類擴(kuò)展的詳解與區(qū)別