KVO
KVO:鍵值觀察。觀察者模式的衍生,對(duì)目標(biāo)對(duì)象的屬性添加觀察,當(dāng)該屬性發(fā)生變化時(shí),通過觸發(fā)觀察者對(duì)象實(shí)現(xiàn)KVO接口方法,來自動(dòng)的通知觀察者。
KVO底層實(shí)現(xiàn):某個(gè)類的對(duì)象第一次被觀察時(shí),系統(tǒng)會(huì)在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建該類的一個(gè)派生類,并在派生類中重寫setter方法,在setter方法實(shí)現(xiàn)真正的通知機(jī)制(如:Person-》NSKVONotifying_Person),外部調(diào)用的類其實(shí)調(diào)用的是這個(gè)派生類。系統(tǒng)對(duì)象的isa指針指向新的派生類,對(duì)setter的調(diào)用就激活鍵值通知機(jī)制。
KVO與Notification之間的區(qū)別:
notification是需要一個(gè)發(fā)送notification的對(duì)象,一般是notificationCenter,來通知觀察者
KVO是直接通知到觀察對(duì)象,并且邏輯非常清晰,實(shí)現(xiàn)步驟簡(jiǎn)單
KVO?例子:
? ? 添加觀察者:? ?[a ????addObserver:b? ? forKeyPath:@"name"? ? options:kNilOptions? ? ?context:nil];? ??
? ? 在觀察者中實(shí)現(xiàn)監(jiān)聽方法,observeValueForKeyPath: ofObject: change: context:
? ? 移除觀察者:? ? [a? ? removeObserver:b? forKeyPath:@"name"];
? ? 數(shù)據(jù)修改:? ? a.name = @"zzz"
KVC
KVC:鍵值編碼。開發(fā)者通過key名直接訪問對(duì)象的屬性,或者給對(duì)象的屬性賦值,而不需要調(diào)用明確的存取方法。這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)訪問和修改對(duì)象的屬性,而不是在編譯時(shí)確定。
KVC底層實(shí)現(xiàn):
(1).KVC取值:
? ? 1.首先查找getter方法,找到的話直接調(diào)用。如果是BOOL或者Int等值,將其包裝成一個(gè)NSNumber對(duì)象。
? ? 2.如果對(duì)象的getter沒有找到,KVC則會(huì)查找countOf,objectInAtIndex或AtIndexes格式的方法。如果找到countOf和(objectInAtIndex或AtIndexes中的一個(gè)),那么就會(huì)返回一個(gè)可以響應(yīng)NSArray所有方法的代理集合(NSKeyValueArray,是BSArray的子類)。
? ? 3.如果上面的方法都沒有找到,那么會(huì)同時(shí)查找countOf,enumeratorOf,memberOf格式的方法。如果都找到,返回一個(gè)可以響應(yīng)NSSet所有的方法的代理集合。
? ? 4.如果還沒有找到,再檢查類方法+(BOOL)accessInstanceVariablesDirectly,如果返回YES,會(huì)按照_,_is,is的順序搜索成員變量。不推薦這樣做。如果重寫+(BOOL)accessInstanceVariablesDirectly返回NO的話,那么會(huì)直接調(diào)用valueForUndefinedKey:方法,默認(rèn)是拋出異常。
(2).KVC設(shè)值:
? ? 1.程序優(yōu)先調(diào)用set屬性值方法,代碼通過setter方法完成設(shè)置
? ? 2.如果沒有找到setName方法,KVC機(jī)制會(huì)檢查+(BOOL)accessInstanceVariablesDirectly方法
? ? 3.如果該類即沒有set方法,也沒有_成員變量,KVC機(jī)制會(huì)搜索_is的成員變量
? ? 4.和上面一樣,沒有set方法,也沒有_和_is成員變量,KVC機(jī)制再會(huì)繼續(xù)搜索和is的成員變量
? ? 5.如果上面列出的方法或者變量都不存在,系統(tǒng)將會(huì)執(zhí)行該對(duì)象的setValue:forUndefinedKey:方法,默認(rèn)跑出異常
(3).KVC 例子
? ? ?1.對(duì)私有變量進(jìn)行賦值:[p setValue:@"張三"? ? forKey:@"name"]? ? [p setValue:@200? ? forKeyPath:@"dog.weight"]
? ? ?2.字典轉(zhuǎn)模型? ? [self? ? setValuesForKeysWithDictionary:dict]