鍵路徑(keyPath)
在一個(gè)給定的實(shí)體中,同一個(gè)屬性的所有值具有相同的數(shù)據(jù)類型屋讶。
鍵-值編碼技術(shù)用于進(jìn)行這樣的查找—它是一種間接訪問對(duì)象屬性的機(jī)制商虐。
鍵路徑是一個(gè)由用點(diǎn)作分隔符的鍵組成的字符串,用于指定一個(gè)連接在一起的對(duì)象性質(zhì)序列。
第一個(gè)鍵的性質(zhì)是由先前的性質(zhì)決定的,接下來每個(gè)鍵的值也是相對(duì)于其前面的性質(zhì)稻爬。
鍵路徑使您可以以獨(dú)立于模型實(shí)現(xiàn)的方式指定相關(guān)對(duì)象的性質(zhì)嗜闻。
通過鍵路徑,您可以指定對(duì)象圖中的一個(gè)任意深度的路徑,使其指向相關(guān)對(duì)象的特定屬性。
鍵值編碼(KVC)
鍵值編碼是一種間接訪問對(duì)象的屬性使用字符串來標(biāo)識(shí)屬性桅锄,
而不是通過調(diào)用存取方法泞辐,直接或通過實(shí)例變量訪問的機(jī)制笔横,
非對(duì)象類型的變量將被自動(dòng)封裝或者解封成對(duì)象,很多情況下會(huì)簡(jiǎn)化程序代碼咐吼;
KVC的缺點(diǎn):
一旦使用 KVC 你的編譯器無法檢查出錯(cuò)誤,即不會(huì)對(duì)設(shè)置的鍵吹缔、鍵路徑進(jìn)行錯(cuò)誤檢查,
且執(zhí)行效率要低于合成存取器方法和自定的 setter 和 getter 方法。
因?yàn)槭褂?KVC 鍵值編碼,它必須先解析字符串,然后在設(shè)置或者訪問對(duì)象的實(shí)例變量锯茄。
鍵值觀察(KVO)
鍵值觀察機(jī)制是一種能使得對(duì)象獲取到其他對(duì)象屬性變化的通知 厢塘,極大的簡(jiǎn)化了代碼。
實(shí)現(xiàn) KVO 鍵值觀察模式肌幽,被觀察的對(duì)象必須使用 KVC 鍵值編碼來修改它的實(shí)例變量晚碾,
這樣才能被觀察者觀察到。
因此喂急,KVC是KVO的基礎(chǔ)格嘁。
Demo
比如我自定義的一個(gè)button
[self?addObserver:self?forKeyPath:@"highlighted"options:0?context:nil];
#pragma?mark?KVO
-?(void)observeValueForKeyPath:(NSString?*)keyPath?ofObject:(id)object?change:(NSDictionary?*)change?context:(void?*)context
{
if([keyPath?isEqualToString:@"highlighted"]?)?{
[self?setNeedsDisplay];
}
}
對(duì)于系統(tǒng)是根據(jù)keypath去取的到相應(yīng)的值發(fā)生改變,理論上來說是和kvc機(jī)制的道理是一樣的廊移。
KVC機(jī)制通過key找到value的原理
當(dāng)通過KVC調(diào)用對(duì)象時(shí)糕簿,比如:[self valueForKey:@”someKey”]時(shí),
程序會(huì)自動(dòng)試圖通過下面幾種不同的方式解析這個(gè)調(diào)用狡孔。
首先查找對(duì)象是否帶有 someKey 這個(gè)方法懂诗,
如果沒找到,會(huì)繼續(xù)查找對(duì)象是否帶有someKey這個(gè)實(shí)例變量(iVar)苗膝,
如果還沒有找到殃恒,程序會(huì)繼續(xù)試圖調(diào)用 -(id) valueForUndefinedKey:這個(gè)方法。
如果這個(gè)方法還是沒有被實(shí)現(xiàn)的話辱揭,程序會(huì)拋出一個(gè)NSUndefinedKeyException異常錯(cuò)誤离唐。
補(bǔ)充:
KVC查找方法的時(shí)候,
不僅僅會(huì)查找someKey這個(gè)方法问窃,
還會(huì)查找getsomeKey這個(gè)方法侯繁,
前面加一個(gè)get,或者_(dá)someKey以_getsomeKey這幾種形式泡躯。
同時(shí)贮竟,查找實(shí)例變量的時(shí)候也會(huì)不僅僅查找someKey這個(gè)變量,
也會(huì)查找_someKey這個(gè)變量是否存在较剃。
設(shè)計(jì)valueForUndefinedKey:方法的主要目的是
當(dāng)你使用-(id)valueForKey方法從對(duì)象中請(qǐng)求值時(shí)咕别,
對(duì)象能夠在錯(cuò)誤發(fā)生前写穴,有最后的機(jī)會(huì)響應(yīng)這個(gè)請(qǐng)求惰拱。
在 Objective-C 中如何實(shí)現(xiàn) KVO
注冊(cè)觀察者(注意:觀察者和被觀察者不會(huì)被保留也不會(huì)被釋放)
-?(void)addObserver:(NSObject?*)observer
forKeyPath:(NSString?*)keyPath
options:(NSKeyValueObservingOptions)options
context:(void?*)context;
接收變更通知
-?(void)observeValueForKeyPath:(NSString?*)keyPath
ofObject:(id)object
change:(NSDictionary?*)change
context:(void?*)context;
移除對(duì)象的觀察者身份
-?(void)removeObserver:(NSObject?*)observer
forKeyPath:(NSString?*)keyPath;
KVO中誰要監(jiān)聽誰注冊(cè)啊送,然后對(duì)響應(yīng)進(jìn)行處理欣孤,使得觀察者與被觀察者完全解耦。
KVO只檢測(cè)類中的屬性昔逗,并且屬性名都是通過NSString來查找降传,
編譯器不會(huì)檢錯(cuò)和補(bǔ)全勾怒,全部取決于自己。