KVO與KVC簡(jiǎn)單理解

KVO與KVC簡(jiǎn)單理解

///////////////////////////////////////我是該死的分割線(xiàn)/////////////////////////

KVO,即:Key-Value Observing,翻譯過(guò)來(lái)就是鍵--值--觀(guān)察.它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后,則對(duì)象就會(huì)接受到通知。簡(jiǎn)單的說(shuō)就是每次指定的被觀(guān)察的對(duì)象的屬性被修改后,KVO就會(huì)自動(dòng)通知相應(yīng)的觀(guān)察者了。

系統(tǒng)框架已經(jīng)支持KVO,所以我們要做的就是如何用了.

1. 注冊(cè),指定被觀(guān)察者的屬性,//誰(shuí)要觀(guān)察,誰(shuí)的屬性改變通知你.

[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];

//對(duì)象 ?添加觀(guān)察者:我自己 哪個(gè)屬性:price屬性 可選項(xiàng):模式|模式 ?上下文:空

這樣就把注冊(cè),指定觀(guān)察者屬性都做完了

2. 實(shí)現(xiàn)回調(diào)方法//通知了你,你得做點(diǎn)事吧.

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context

{

if([keyPath isEqualToString:@"price"])

{

myLabel.text = [stockForKVO valueForKey:@"price"];

}

}

//在這個(gè)方法里寫(xiě)通知你之后干的事,像例子說(shuō)的那樣,先判斷是不是這個(gè)屬性,然后再賦值.判斷這一步不能少,如果同時(shí)好多人在觀(guān)察,可能搞混淆.這里得引入和通知的區(qū)別了.

//KVO與通知區(qū)別:

通知:是一種廣播機(jī)制,在實(shí)踐發(fā)生的時(shí)候,通過(guò)通知中心對(duì)象,一個(gè)對(duì)象能夠?yàn)樗嘘P(guān)心這個(gè)時(shí)間發(fā)生的對(duì)象發(fā)送消息,兩者都是觀(guān)察者模式,不同在于KVO是被觀(guān)察者直接發(fā)送消息給觀(guān)察者,是對(duì)象間的直接交互,通知?jiǎng)t是兩者都和通知中心對(duì)象交互,對(duì)象之間不知道彼此

KVO使用:被觀(guān)察著發(fā)生addobserver:forkeyPath:options:context:方法來(lái)添加觀(guān)察者.然后只要被觀(guān)察者的keypath值發(fā)生變化(注意單純改變值不會(huì)調(diào)用此方法,只有通過(guò)getter和sett來(lái)改變值才會(huì)觸發(fā)KVO),就會(huì)在觀(guān)察者里調(diào)用方法observerValueForKeyPath:ofobject:change:context:因此實(shí)現(xiàn)此方法來(lái)對(duì)KVO發(fā)出的通知做出響應(yīng).

這些代碼都是秩序在觀(guān)察者里進(jìn)行實(shí)現(xiàn),被觀(guān)察者不用添加任何代碼,所以誰(shuí)要監(jiān)聽(tīng)誰(shuí)要注冊(cè),然后對(duì)響應(yīng)進(jìn)行處理即可,使得觀(guān)察者與被觀(guān)察者完全解耦,運(yùn)用很靈活很簡(jiǎn)便,但是KVO只能檢測(cè)類(lèi)中屬性,并且屬性名都是通過(guò)NSString來(lái)查找,編譯器不會(huì)幫你檢測(cè)對(duì)錯(cuò)和補(bǔ)全,純手敲會(huì)比較容易出錯(cuò)

通知的使用:通知的發(fā)出是由通知中心來(lái)統(tǒng)一發(fā)出,而不同通知通過(guò)唯一標(biāo)示名notifcationName來(lái)區(qū)分,標(biāo)示名由發(fā)送通知的類(lèi)來(lái)起.首先被觀(guān)察者自己在必要的方法A里,通過(guò)方法postNotificationName:object:發(fā)出通知notificationName這樣發(fā)送通知著這邊的工作就完成了,每次A被調(diào)用,就會(huì)發(fā)送一次通知notificationName

然后誰(shuí)要監(jiān)聽(tīng)A的變化,就通過(guò)[NSNotificationCenter defaultCenter] 的方法addobserver:sslector:name:object為觀(guān)察者注冊(cè)監(jiān)聽(tīng)name為notificationNmae的通知.

每次發(fā)出name為notificationNmae的通知時(shí),注冊(cè)監(jiān)聽(tīng)后的觀(guān)察著就會(huì)調(diào)用其自己定義的方法notificationselector來(lái)進(jìn)行相應(yīng)

NSNotification的特點(diǎn),就是需要被觀(guān)察者先主動(dòng)發(fā)出通知,然后觀(guān)察者注冊(cè)監(jiān)聽(tīng)后,再來(lái)進(jìn)行響應(yīng),比KVO多了發(fā)送通知的一步,但是其優(yōu)點(diǎn)是監(jiān)聽(tīng)不局限屬性的變化,還可以對(duì)多種多樣的狀態(tài)變化進(jìn)行監(jiān)聽(tīng),監(jiān)聽(tīng)范圍廣,使用靈活.

3. 移除觀(guān)察//不會(huì)自動(dòng)移除,需要手動(dòng)移除

增加觀(guān)察與取消觀(guān)察是成對(duì)出現(xiàn)的,所以需要在最后的時(shí)候,移除觀(guān)察者

///////////////////////////////////////我是該死的分割線(xiàn)//////////////////////////

KVC是KeyValueCoding的簡(jiǎn)稱(chēng),翻譯過(guò)來(lái)是鍵值編碼,它是一種可以直接通過(guò)字符串的名字(key)來(lái)訪(fǎng)問(wèn)類(lèi)屬性(實(shí)例變量)的機(jī)制。而不是通過(guò)調(diào)用Setter、Getter方法(點(diǎn)語(yǔ)法)訪(fǎng)問(wèn)。

當(dāng)使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)時(shí),KVC是關(guān)鍵技術(shù)。

//

關(guān)鍵方法定義在:NSKeyValueCodingprotocol

The NSKeyValueCoding informal protocol defines a mechanism by which you can access the properties of an object indirectly by name (or key), rather than directly through invocation of an accessor method or as instance variables. Thus, all of an object’s properties can be accessed in a consistent manner.

這個(gè)鍵值編碼非正式協(xié)議定義了一個(gè)機(jī)制通過(guò)你可以間接的獲取一個(gè)對(duì)象的屬性通過(guò)名字(或者叫key),而不是直接通過(guò)調(diào)用訪(fǎng)問(wèn)器方法或者實(shí)例變量.因此,一個(gè)對(duì)象的所有屬性可以被存取用一個(gè)通用的方式.

The basic methods for accessing an object’s values are setValue:forKey:, which sets the value for the property identified by the specified key, and valueForKey:, which returns the value for the property identified by the specified key. The default implementation uses the accessor methods normally implemented by objects (or to access instance variables directly if need be).

這個(gè)基本方法對(duì)于訪(fǎng)問(wèn)一個(gè)對(duì)象的值是 setValue:forKey用來(lái)設(shè)置值對(duì)于可識(shí)別的屬性通過(guò)規(guī)定的key,和valueForKey用來(lái)返回一個(gè)值對(duì)于可識(shí)別的屬性通過(guò)規(guī)定的key.這個(gè)默認(rèn)的實(shí)現(xiàn)使用了訪(fǎng)問(wèn)器方法正常的實(shí)現(xiàn)通過(guò)對(duì)象(或者通過(guò)實(shí)例變量如果需要的話(huà)).

Default Search Pattern for setValue:forKey://默認(rèn)查找模式對(duì)于setValue:forKey

When the default implementation ofsetValue:forKey:is invoked for a property the following search pattern is used:

當(dāng)這個(gè)默認(rèn)實(shí)現(xiàn)setValue:forKey是屬性調(diào)用模式是使用下列搜索模式

The receiver’s class is searched for an accessor method whose name matches the pattern set:.

接收器的類(lèi)去搜索訪(fǎng)問(wèn)器方法的名字匹配這個(gè)設(shè)置模式.

If no accessor is found, and the receiver’s class method accessInstance VariablesDirectlyreturns?YES, the receiver is searched for an instance variable whose name matches the pattern, _<key>,_is<key>,<key>,is<key>,in that order.

如果訪(fǎng)問(wèn)器方法沒(méi)有找到,而且接受方法accessInstance VariablesDirectlyreturns返回yes,接受器將會(huì)搜索實(shí)例變量的名字匹配,在這種情況下.

If a matching accessor or instance variable is located, it is used to set the value. If necessary, the value is extracted from the object as described inRepresenting Non-Object Values.

如果匹配訪(fǎng)問(wèn)器方法或?qū)嵗兞慷技虞d了,它通常使用set the value.如果必要的話(huà),值引出從對(duì)象像Representing Non-Object Values文檔描述的一樣.

If no appropriate accessor or instance variable is found,setValue:forUndefinedKey:is invoked for the receiver.

如果都沒(méi)有找到的話(huà),將會(huì)喚醒setValue:forUndefinedKey給接收器.//一般拋出異常,可重寫(xiě).

//在字典轉(zhuǎn)模型里,服務(wù)器返回的數(shù)據(jù)有些不想要就重寫(xiě)這個(gè)方法.

Default Search Pattern for valueForKey://默認(rèn)搜索模式對(duì)于valueForKey

When the default implementation of valueForKey:is invoked on a receiver, the following search pattern is used:

//當(dāng)默認(rèn)實(shí)現(xiàn)valueForKey是調(diào)用在接收器,通常使用以下搜索模式

Searches the class of the receiver for an accessor method whose name matches the pattern get<key>,<key>,is<key>, in that order. If such a method is found it is invoked. If the type of the method's result is an object pointer type the result is simply returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint,NSRange,NSRect, and NSSize types).

搜索接受者類(lèi)從訪(fǎng)問(wèn)器方法的名字匹配參數(shù)get<key>,<key>,is<key>,在那種情況下.如果發(fā)現(xiàn)這個(gè)方法被調(diào)用了,如果這個(gè)方法飛返回類(lèi)型是一個(gè)對(duì)象指針類(lèi)型,這個(gè)結(jié)果簡(jiǎn)單的返回.如果這個(gè)結(jié)果類(lèi)型是數(shù)量的一種,將轉(zhuǎn)換為NSNumber返回,否則,轉(zhuǎn)換NSValue返回.任意的結(jié)果類(lèi)型都是轉(zhuǎn)換成NSValue類(lèi)了,不只是NSPoint,NSRange,NSRect, and NSSize types.

Otherwise (no simple accessor method is found), searches the class of the receiver for methods whose names match the patterns countOf?and objectInAtIndex:(corresponding to the primitive methods defined by the NSArray class) andAtIndexes:(corresponding to the?NSArray??method ?objectsAtIndexes:). If the countOf?method and at least one of the other two possible methods are found, a collection proxy object that responds to all NSArray methods is returned. Each NSArray message sent to the collection proxy object will result in some combination of countOf,objectInAtIndex:, andAtIndexes:messages being sent to the original receiver of?valueForKey:. If the class of the receiver also implements an optional method whose name matches the pattern get:range:that method will be used when appropriate for best performance.

否則(沒(méi)有找到簡(jiǎn)單訪(fǎng)問(wèn)器方法),搜索這個(gè)接受器的類(lèi)從方法匹配參數(shù)countOfand objectInAtIndex(相當(dāng)于去用原始方法定義在NSArray 類(lèi)里)andAtIndexes(相當(dāng)于去用這個(gè)NSArray方法 andAtIndexes).如果countOf方法至少一到兩個(gè)可能的方法被找到,一個(gè)集合代理對(duì)象對(duì)于所有的NSArray methods將會(huì)被返回,每一個(gè)NSArray 消息發(fā)送給集合代理對(duì)象將會(huì)返回countOf,objectInAtIndex,andAtIndexes組合.消息將要發(fā)送給valueForKey的原始接受者,如果這個(gè)接受者的類(lèi)也實(shí)現(xiàn)一個(gè)可選方法,是名字匹配參數(shù)get:range:,那方法將會(huì)使用當(dāng)合適為了做好的執(zhí)行.

Otherwise (no simple accessor method or set of array access methods is found), searches the class of the receiver for a threesome of methods whose names match the patterns countOf,enumeratorOf, and memberOf:(corresponding to the primitive methods defined by theNSSet?class). If all three methods are found, a collection proxy object that responds to all NSSet methods is returned. Each NSSet message sent to the collection proxy object will result in some combination of countOf,enumeratorOf, and memberOf:messages being sent to the original receiver of?valueForKey:.

否則(訪(fǎng)問(wèn)器方法和set of array access methods都沒(méi)有找到),搜索接收器的類(lèi)將從一個(gè)三人組方法,是名字匹配模式countOf,enumeratorOf, and memberOf(相當(dāng)于使用原始方法定義在NSSet類(lèi)里),如果都三個(gè)方法都找到了,一個(gè)集合代理對(duì)象將會(huì)響應(yīng)所有的NSSet方法并返回.每一個(gè)NSSet 消息發(fā)送給集合代理對(duì)象將會(huì)生成countOf,enumeratorOf, andmemberOf組合,消息將會(huì)被發(fā)送去這的valueForKey原始接受器.

Otherwise (no simple accessor method or set of collection access methods is found), if the receiver's class method?accessInstanceVariablesDirectly?returnsYES, the class of the receiver is searched for an instance variable whose name matches the pattern_,_is,, oris, in that order. If such an instance variable is found, the value of the instance variable in the receiver is returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted toNSValueobjects, not justNSPoint,NSRange,NSRect, andNSSizetypes.

否則(沒(méi)有找到簡(jiǎn)單訪(fǎng)問(wèn)器方法和set of collection access methods的一種),如果接收器的類(lèi)方法

accessInstanceVariablesDirectly返回yes,這個(gè)接收器的類(lèi)將會(huì)搜索實(shí)例變量,是名字匹配參數(shù)

_<key>,_is<key>,<key>,is<key>,在這種情況下.如果找到了實(shí)例變量,這個(gè)實(shí)例變量的值將會(huì)被返回.如果結(jié)果的類(lèi)型是數(shù)量類(lèi)型的一種,將轉(zhuǎn)換成NSNumber并返回,否則,轉(zhuǎn)換為NSValue返回.任意的結(jié)果類(lèi)型都是轉(zhuǎn)換成NSValue類(lèi)了,不只是NSPoint,NSRange,NSRect, and NSSize types.

If none of the above situations occurs, returns a result the default implementation invokes?valueForUndefinedKey:.

如果沒(méi)有出現(xiàn)上述情況,返回默認(rèn)實(shí)現(xiàn)結(jié)果調(diào)用valueForUndefinedKey.

KVC支持類(lèi)對(duì)象和內(nèi)建基本數(shù)據(jù)類(lèi)型。

獲取值

valueForKey:,傳入NSString屬性的名字。

valueForKeyPath:,傳入NSString屬性的路徑,xx.xx形式。

valueForUndefinedKey它的默認(rèn)實(shí)現(xiàn)是拋出異常,可以重寫(xiě)這個(gè)函數(shù)做錯(cuò)誤處理。

修改值

setValue:forKey:

setValue:forKeyPath:

setValue:forUndefinedKey:

setNilValueForKey:當(dāng)對(duì)非類(lèi)對(duì)象屬性設(shè)置nil時(shí),調(diào)用,默認(rèn)拋出異常。

一對(duì)多關(guān)系成員的情況

mutableArrayValueForKey:有序一對(duì)多關(guān)系成員??NSArray

mutableSetValueForKey:無(wú)序一對(duì)多關(guān)系成員??NSSet

最后編輯于
?著作權(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)容