天天看點

iOS:KVC和KVO

來源:  對月流      

寫在前面:

關于KVC和KVO各種部落格多了去了,重新整理下,就當是溫習一下吧,也還算是個新手,不對的地方請指教,喜歡的點個喜歡什麼也是挺好。

一,KVC

KVC也就是key-value-coding,即鍵值編碼,通常是用來給某一個對象的屬性進行指派,例如有人這麼一個類,其對外有兩個屬性,姓名和年齡,我們在建立了一個人p後可以通過點文法直接給p指派。

我們也可以通過kvc給這個人p指派,代碼如下,因為setValue這裡的值是id類型的,是以将整數包裝成一個對象

但是我們這樣去指派顯得多此一舉,可是如果人這個類的屬性是沒有暴露在外面呢?比如現在給人這個類一個私有的身高的屬性,并且對外提供一個輸出身高的接口,如下

iOS:KVC和KVO
iOS:KVC和KVO

這時候我們是沒有辦法去給人p直接設定身高的,外面我們通路不到它.但是有了kvc就不一樣了。

我們通過kvc可以直接對私有屬性進行指派,列印如下

iOS:KVC和KVO

除了[p setValue:@170 forKey:@"height"]這個方法外,還有一個方法也是可以對私有屬性進行指派的[p setValue:@170 forKeyPath:@"height"];這兩個方法對于一個普通的屬性是沒有差別的,都可以用,但是對于一些特殊的屬性就有差別了。

比如說人這個類有個屬性是狗,狗又有屬性體重。

如果我們直接這樣是會報錯說找不到dog.weight這個key的,而在storyboard中,我們拖控件連線錯誤的時候也會報錯說找不到什麼key,說明storyboard在指派的時候也是通過kvc來操作的。 

這裡如果我們換另外的一個方法,這時候是不會報錯的,而且可以列印出狗的體重.

說明forKeyPath是包含了forKey這個方法的功能的,甚至forKeyPath方法還有它自己的進階的功能,它會先去找有沒有dog這個key,然後去找有沒有weight這個屬性。是以我們在使用kvc的時候,最好用forKeyPath這個方法。

最後還有一點,如下代碼

我們傳入的字元串key是height,但是定義的屬性是_height,但是通過kvc還是可以給_height屬性賦到值。說明對某一個屬性進行指派,可以不用加下劃線,而且它的查找規則應該是:先查找和直接寫入的字元串相同的成員變量,如果找不到就找以下劃線開頭的成員變量。

kvc除了通路私有變量這個用處外,還可以用于字典轉模型。在Person類對外提供一個接口,将轉模型的工作放在模型中進行

iOS:KVC和KVO
iOS:KVC和KVO

外面可以直接将字典傳入,和平常轉模型相比,kvc更加友善,減少了代碼量。

是以kvc最常見的兩種用法就是:

1,對私有變量進行指派

2,字典轉模型

但是也有一些需要注意的地方

1,字典轉模型的時候,字典中的某一個key一定要在模型中有對應的屬性

2,如果一個模型中包含了另外的模型對象,是不能直接轉化成功的。

3,通過kvc轉化模型中的模型,也是不能直接轉化成功的。

既然可以通過kvc指派,同樣的也可以通過它進行取值。

二,KVO

KVO,即key-value-observing,利用一個key來找到某個屬性并監聽其值得改變。其實這也是一種典型的觀察者模式。

簡單的說,kvo的用法非常簡單。

1,添加觀察者

2,在觀察者中實作監聽方法,observeValueForKeyPath: ofObject: change: context:(通過查閱文檔可以知道,絕大多數對象都有這個方法,因為這個方法屬于NSObject)

3,移除觀察者

具體代碼如下:

iOS:KVC和KVO
iOS:KVC和KVO

KVO的底層實作

當一個類的屬性被觀察的時候,系統會通過runtime動态的建立一個該類的派生類,并且會在這個類中重寫基類被觀察的屬性的setter方法,而且系統将這個類的isa指針指向了派生類,進而實作了給監聽的屬性指派時調用的是派生類的setter方法。重寫的setter方法會在調用原setter方法前後,通知觀察對象值得改變。

具體實作圖如下,這裡我拿的是iOS程式猿的圖,借用一下應該沒關系吧?

iOS:KVC和KVO

最後

貌似有個facebook開源的工具,KVOController ,是一個簡單安全的 KVO(Key-value Observing,鍵-值 觀察)工具,好像挺好用的。

程式猿神奇的手,每時每刻,這雙手都在改變着世界的互動方式!

本文轉自當天真遇到現實部落格園部落格,原文連結:http://www.cnblogs.com/XYQ-208910/p/5286278.html,如需轉載請自行聯系原作者