分類
分類的作用
分解體積龐大的類文件
為系統(tǒng)類添加方法
聲明私有方法
把Framework的私有方法公開
分類添加過(guò)程
在程序運(yùn)行時(shí)候闺鲸,runtime會(huì)把分類的實(shí)例方法等信息合并到類對(duì)象的實(shí)例方法列表中舟奠,會(huì)把分類的類方法合并到元類對(duì)象的類方法列表中(在原方法之前)畸写。
以添加實(shí)例方法為例:
運(yùn)行時(shí)候,會(huì)遍歷分類列表,拿到每一個(gè)分類的實(shí)例方法列表
分類能添加成員變量嗎?
不能盾舌。只能通過(guò)關(guān)聯(lián)對(duì)象(objc_setAssociatedObject)來(lái)模擬實(shí)現(xiàn)成員變量,但其實(shí)質(zhì)是關(guān)聯(lián)內(nèi)容蘸鲸,所有對(duì)象的關(guān)聯(lián)內(nèi)容都放在同一個(gè)全局容器哈希表中:AssociationsHashMap,由AssociationsManager統(tǒng)一管理妖谴。
#關(guān)聯(lián)對(duì)象: 使用objc_setAssociatedObject函數(shù)可以給某個(gè)對(duì)象關(guān)聯(lián)其他的對(duì)象。
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
#獲取關(guān)聯(lián)的對(duì)象: 使用objc_getAssociatedObject函數(shù)可以通過(guò)鍵來(lái)取出某個(gè)對(duì)象的關(guān)聯(lián)對(duì)象棚贾。
id objc_getAssociatedObject(id object, const void *key)
#移除關(guān)聯(lián)的對(duì)象:使用objc_removeAssociatedObjects函數(shù)可以移除某個(gè)對(duì)象身上的所有關(guān)聯(lián)的對(duì)象窖维。
void objc_removeAssociatedObjects(id object)
?
?
?
擴(kuò)展
一般用擴(kuò)展做什么?
聲明私有屬性妙痹,聲明方法(沒(méi)什么意義)铸史,聲明私有成員變量
擴(kuò)展的特點(diǎn)
編譯時(shí)決議,只能以聲明的形式存在怯伊,多數(shù)情況下寄生在宿主類的.m中琳轿,不能為系統(tǒng)類添加擴(kuò)展。
分類跟擴(kuò)展的區(qū)別
擴(kuò)展:在編寫完分類文件后耿芹,直接把分類內(nèi)容添加到相關(guān)的宿主類上崭篡。
分類:是在運(yùn)行時(shí)使用runtime把分類的內(nèi)容添加到宿主類上。
?
?
?
代理
代理是一種設(shè)計(jì)模式吧秕,以@protocol形式體現(xiàn)琉闪。
一般是一對(duì)一傳遞,一般以weak關(guān)鍵詞以規(guī)避循環(huán)引用砸彬。
本質(zhì)是獲得對(duì)象颠毙,調(diào)用方法返回?cái)?shù)據(jù)。
?
?
?
通知
使用觀察者模式來(lái)實(shí)現(xiàn)的用于跨層傳遞信息的機(jī)制砂碉。
傳遞方式是一對(duì)多的蛀蜜。
原理是在通知中心維護(hù)一個(gè)map表,key為通知的名稱增蹭,value為observer滴某。本質(zhì)為持有對(duì)象,所以在不用時(shí)滋迈,需要釋放對(duì)象霎奢。
?
?
?
KVO
使用觀察者設(shè)計(jì)模式,使用isa混寫技術(shù)。
當(dāng)A類實(shí)例被KVO監(jiān)聽時(shí)饼灿,Runtime會(huì)轉(zhuǎn)建一個(gè)繼承自A類的新類NSKVONotifying_A椰憋,并重寫被觀察屬性的setter和getter方法。如果代碼中有創(chuàng)建NSKVONotifying_A類赔退,注冊(cè)A類KVO時(shí)會(huì)崩潰。
何時(shí)觸發(fā):
使用setter方法改變值時(shí),會(huì)觸發(fā)KVO硕旗;
使用KVC setValue:forKey:改變值時(shí)窗骑,會(huì)觸發(fā)KVO;
成員變量直接修改漆枚,不會(huì)觸發(fā)KVO创译,需手動(dòng)添加willChangeValueForKey和didChangeValueForKey方法才會(huì)觸發(fā);
- (void)setName:(NSString *)newName {
[self willChangeValueForKey:@"name"]; //KVO 在調(diào)用存取方法之前總調(diào)用
[super setValue:newName forKey:@"name"]; //調(diào)用父類的存取方法
[self didChangeValueForKey:@"name"]; //KVO 在調(diào)用存取方法之后總調(diào)用
}
~
~
~
KVC
KVC的全稱是Key-Value Coding墙基,俗稱“鍵值編碼”软族,可以通過(guò)一個(gè)key來(lái)訪問(wèn)某個(gè)屬性。KVC的操作方法由NSKeyValueCoding提供残制,而他是NSObject的類別立砸,也就是說(shuō)ObjC中幾乎所有的對(duì)象都支持KVC操作。
常用方法
獲取值的方法
valueForKey:初茶,傳入NSString屬性的名字颗祝。
valueForKeyPath:,傳入NSString屬性的路徑恼布,xx.xx形式螺戳。
valueForUndefinedKey它的默認(rèn)實(shí)現(xiàn)是拋出異常,可以重寫這個(gè)函數(shù)做錯(cuò)誤處理折汞。
修改值的方法
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setValue:forKey的搜索過(guò)程:
- 首先搜索set<Key>:方法
如果成員用@property倔幼,@synthsize處理,因?yàn)锧synthsize告訴編譯器自動(dòng)生成set<Key>:格式的setter方法爽待,所以這種情況下會(huì)直接搜索到损同。
注意:這里的<Key>是指成員名,而且首字母大寫堕伪。 - 上面的setter方法沒(méi)有找到揖庄,如果類方法accessInstanceVariablesDirectly返回YES(注:這是NSKeyValueCodingCatogery中實(shí)現(xiàn)的類方法,默認(rèn)實(shí)現(xiàn)為返回YES)欠雌。
那么按_<key>蹄梢,_is<Key>,<key>富俄,is<key>的順序搜索成員名禁炒。 - 如果還是沒(méi)有找到設(shè)置成員的值,就會(huì)調(diào)用setValue:forUndefinedKey:霍比。
- 如果沒(méi)有重寫setValue:forUndefinedKey程序會(huì)馬上崩潰幕袱。
?
?
?
屬性關(guān)鍵字
1.讀寫權(quán)限:readonly,readwrite(默認(rèn))
2.原子性: atomic(默認(rèn)),nonatomic悠瞬。atomic讀寫線程安全们豌,但效率低涯捻,而且不是絕對(duì)的安全,比如如果修飾的是數(shù)組望迎,那么對(duì)數(shù)組的讀寫是安全的障癌,但如果是操作數(shù)組進(jìn)行添加移除其中對(duì)象的還,就不保證安全了辩尊。
3.引用計(jì)數(shù):
retain/strong:引用計(jì)數(shù)加1
assign:修飾基本數(shù)據(jù)類型涛浙,修飾對(duì)象類型時(shí),不改變其引用計(jì)數(shù)摄欲,會(huì)產(chǎn)生懸垂指針轿亮,修飾的對(duì)象在被釋放后,assign指針仍然指向原對(duì)象內(nèi)存地址胸墙,如果使用assign指針繼續(xù)訪問(wèn)原對(duì)象的話我注,就可能會(huì)導(dǎo)致內(nèi)存泄漏或程序異常
weak:不改變被修飾對(duì)象的引用計(jì)數(shù),所指對(duì)象在被釋放后劳秋,weak指針會(huì)自動(dòng)置為nil
copy:分為深拷貝和淺拷貝
淺拷貝:對(duì)內(nèi)存地址的復(fù)制仓手,讓目標(biāo)對(duì)象指針和原對(duì)象指向同一片內(nèi)存空間會(huì)增加引用計(jì)數(shù)
深拷貝:對(duì)對(duì)象內(nèi)容的復(fù)制,開辟新的內(nèi)存空間
可變對(duì)象的copy和mutableCopy都是深拷貝
不可變對(duì)象的copy是淺拷貝玻淑,mutableCopy是深拷貝
copy方法返回的都是不可變對(duì)象
@property (nonatomic, copy) NSMutableArray * array;這樣寫有什么影響嗽冒?
因?yàn)閏opy方法返回的都是不可變對(duì)象,所以array對(duì)象實(shí)際上是不可變的补履,如果對(duì)其進(jìn)行可變操作如添加移除對(duì)象添坊,則會(huì)造成程序crash。
?
?
?
參考:Objective_C語(yǔ)言特性:分類箫锤、擴(kuò)展
參考: iOS開發(fā)-OC篇-KVC詳解