整理資料. ??
深入淺出理解分類(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ū)別