iOS開發之--路徑(keyPath)、鍵值編碼(KVC)和鍵值觀察(KVO)


鍵路徑

  • 在一個給定的實體中,同一個屬性的所有值具有相同的數據類型。

  • 鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。 - 鍵路徑是一個由用點作分隔符的鍵組成的字符串,用於指定一個連接在一起的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每個鍵的值也是相對於其前面的性質。

  • 鍵路徑使您可以以獨立於模型實現的方式指定相關對象的性質。通過鍵路徑,您可以指定對象圖中的一個任意深度的路徑,使其指向相關對象的特定屬性。

鍵值編碼KVC

  • 鍵值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是通過調用存取方法,直接或通過實例變量訪問的機制,非對象類型的變量將被自動封裝或者解封成對象,很多情況下會簡化程序代碼;

  • KVC的缺點:一旦使用 KVC 你的編譯器無法檢查出錯誤,即不會對設置的鍵、鍵路徑進行錯誤檢查,且執行效率要低於合成存取器方法和自定的 setter 和 getter 方法。因為使用 KVC 鍵值編碼,它必須先解析字符串,然后在設置或者訪問對象的實例變量。

鍵值觀察KVO

  • 鍵值觀察機制是一種能使得對象獲取到其他對象屬性變化的通知 ,極大的簡化了代碼。

  • 實現 KVO 鍵值觀察模式,被觀察的對象必須使用 KVC 鍵值編碼來修 改它的實例變量,這樣才能被觀察者觀察到。因此,KVC是KVO的基礎。

Demo

比如我自定義的一個button

1
2
3
4
5
6
7
8
[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]; 
  }

對於系統是根據keypath去取的到相應的值發生改變,理論上來說是和kvc機制的道理是一樣的。

KVC機制通過key找到value的原理。

  • 當通過KVC調用對象時,比如:[self valueForKey:@”someKey”]時,程序會自動試圖通過下面幾種不同的方式解析這個調用。

  • 首 先查找對象是否帶有 someKey 這個方法,如果沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),如果還沒有找到,程序會繼續試圖調用 -(id) valueForUndefinedKey:這個方法。如果這個方法還是沒有被實現的話,程序會拋出一個NSUndefinedKeyException 異常錯誤。

  • 補充:KVC查找方法的時候,不僅僅會查找someKey這個方法,還會查找getsomeKey這個方法, 前面加一個get,或者_someKey以_getsomeKey這幾種形式。同時,查找實例變量的時候也會不僅僅查找someKey這個變量,也會查找 _someKey這個變量是否存在。

  • 設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象能夠在錯誤發生前,有最后的機會響應這個請求。

在 Objective-C 中如何實現 KVO

  • 注冊觀察者(注意:觀察者和被觀察者不會被保留也不會被釋放)

1
2
3
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 
options:(NSKeyValueObservingOptions)options 
context:(void *)context;
  • 接收變更通知

1
2
- (void)observeValueForKeyPath:(NSString *)keyPath 
ofObject:(id)object change:(NSDictionary *)change   context:(void *)context;
  • 移除對象的觀察者身份

1
2
- (void)removeObserver:(NSObject *)observer 
forKeyPath:(NSString *)keyPath;
  • KVO中誰要監聽誰注冊,然后對響應進行處理,使得觀察者與被觀察者完全解耦。KVO只檢測類中的屬性,並且屬性名都是通過NSString來查找,編譯器不會檢錯和補全,全部取決於自己。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM