iOS--KVO的實現(xiàn)原理與具體應(yīng)用(轉(zhuǎn)自看)

iOS--KVO的實現(xiàn)原理與具體應(yīng)用

長時間不用容易忘,這篇文章挺好的.轉(zhuǎn)載自看
本文分為2個部分:概念與應(yīng)用端圈。
概念部分旨在剖析KVO這一設(shè)計模式的實現(xiàn)原理,應(yīng)用部分通過創(chuàng)建的項目朗和,以說明KVO技術(shù)在iOS開發(fā)中所帶來的作用昭伸;
如果是作為是剛接觸KVO的初學(xué)者猛铅,可以在了解基本原理后粗略看幾遍底層實現(xiàn)原理踩官,再認(rèn)真閱讀第二部分的應(yīng)用內(nèi)容“學(xué)會”怎么去使用KVO毁葱,往后再慢慢深入了解KVO這一“黑魔法”技術(shù)的實現(xiàn)原理锡凝。
一、KVO是什么壹哺?
KVO 是 Objective-C 對觀察者設(shè)計模式的一種實現(xiàn)。
KVO提供一種機制艘刚,指定一個被觀察對象(例如A類)管宵,當(dāng)對象某個屬性(例如A中的字符串name)發(fā)生更改時,對象會獲得通知攀甚,并作出相應(yīng)處理箩朴;【且不需要給被觀察的對象添加任何額外代碼,就能使用KVO機制】
在MVC設(shè)計架構(gòu)下的項目秋度,KVO機制很適合實現(xiàn)mode模型和view視圖之間的通訊炸庞。
例如:代碼中,在模型類A創(chuàng)建屬性數(shù)據(jù)荚斯,在控制器中創(chuàng)建觀察者埠居,一旦屬性數(shù)據(jù)發(fā)生改變就收到觀察者收到通知查牌,通過KVO再在控制器使用回調(diào)方法處理實現(xiàn)視圖B的更新;(本文中的應(yīng)用就是這樣的例子.)
二滥壕、實現(xiàn)原理纸颜?
KVO在Apple中的API文檔如下:

image.png

KVO 的實現(xiàn)依賴于 Objective-C 強大的 Runtime,從以上Apple 的文檔可以看出蘋果對于KVO機制的實現(xiàn)是一筆帶過绎橘,而具體的細(xì)節(jié)沒有過多的描述胁孙,但是我們可以通過Runtime的所提供的方法去探索,關(guān)于KVO機制的底層實現(xiàn)原理称鳞。
基本的原理:
當(dāng)觀察某對象A時涮较,KVO機制動態(tài)創(chuàng)建一個對象A當(dāng)前類的子類,并為這個新的子類重寫了被觀察屬性keyPath的setter 方法冈止。setter 方法隨后負(fù)責(zé)通知觀察對象屬性的改變狀況狂票。
深入剖析:
Apple 使用了 isa 混寫(isa-swizzling)來實現(xiàn) KVO 。當(dāng)觀察對象A時靶瘸,KVO機制動態(tài)創(chuàng)建一個新的名為: NSKVONotifying_A的新類苫亦,該類繼承自對象A的本類,且KVO為NSKVONotifying_A重寫觀察屬性的setter 方法怨咪,setter 方法會負(fù)責(zé)在調(diào)用原 setter 方法之前和之后屋剑,通知所有觀察對象屬性值的更改情況。
(備注: isa 混寫(isa-swizzling)isa:is a kind of 诗眨; swizzling:混合唉匾,攪合;)
①NSKVONotifying_A類剖析:在這個過程匠楚,被觀察對象的 isa 指針從指向原來的A類巍膘,被KVO機制修改為指向系統(tǒng)新創(chuàng)建的子類 NSKVONotifying_A類,來實現(xiàn)當(dāng)前類屬性值改變的監(jiān)聽芋簿;
所以當(dāng)我們從應(yīng)用層面上看來峡懈,完全沒有意識到有新的類出現(xiàn),這是系統(tǒng)“隱瞞”了對KVO的底層實現(xiàn)過程与斤,讓我們誤以為還是原來的類肪康。但是此時如果我們創(chuàng)建一個新的名為“NSKVONotifying_A”的類(),就會發(fā)現(xiàn)系統(tǒng)運行到注冊KVO的那段代碼時程序就崩潰撩穿,因為系統(tǒng)在注冊監(jiān)聽的時候動態(tài)創(chuàng)建了名為NSKVONotifying_A的中間類磷支,并指向這個中間類了。
(isa 指針的作用:每個對象都有isa 指針食寡,指向該對象的類雾狈,它告訴 Runtime 系統(tǒng)這個對象的類是什么。所以對象注冊為觀察者時抵皱,isa指針指向新子類善榛,那么這個被觀察的對象就神奇地變成新子類的對象(或?qū)嵗┝吮绲啊#?因而在該對象上對 setter 的調(diào)用就會調(diào)用已重寫的 setter,從而激活鍵值通知機制锭弊。
—>我猜堪澎,這也是KVO回調(diào)機制,為什么都俗稱KVO技術(shù)為黑魔法的原因之一吧:內(nèi)部神秘味滞、外觀簡潔樱蛤。
②子類setter方法剖析:KVO的鍵值觀察通知依賴于 NSObject 的兩個方法:willChangeValueForKey:和didChangevlueForKey:,在存取數(shù)值的前后分別調(diào)用2個方法:
被觀察屬性發(fā)生改變之前剑鞍,willChangeValueForKey:被調(diào)用昨凡,通知系統(tǒng)該 keyPath 的屬性值即將變更;當(dāng)改變發(fā)生后蚁署, didChangeValueForKey: 被調(diào)用便脊,通知系統(tǒng)該 keyPath 的屬性值已經(jīng)變更;之后光戈, observeValueForKey:ofObject:change:context: 也會被調(diào)用哪痰。且重寫觀察屬性的setter 方法這種繼承方式的注入是在運行時而不是編譯時實現(xiàn)的。
KVO為子類的觀察者屬性重寫調(diào)用存取方法的工作原理在代碼中相當(dāng)于:

image.png

三久妆、特點:
觀察者觀察的是屬性晌杰,只有遵循 KVO 變更屬性值的方式才會執(zhí)行KVO的回調(diào)方法,例如是否執(zhí)行了setter方法筷弦、或者是否使用了KVC賦值肋演。如果賦值沒有通過setter方法或者KVC,而是直接修改屬性對應(yīng)的成員變量烂琴,例如:僅調(diào)用_name = @"newName"爹殊,這時是不會觸發(fā)kvo機制,更加不會調(diào)用回調(diào)方法的奸绷。
所以使用KVO機制的前提是遵循 KVO 的屬性設(shè)置方式來變更屬性值梗夸。
四、步驟
注冊觀察者号醉,實施監(jiān)聽绒瘦;
在回調(diào)方法中處理屬性發(fā)生的變化;
移除觀察者
---------------------------------------------------------應(yīng)用---------------------------------------------------------
五.實現(xiàn)方法(蘋果API文檔中的方法):
A.注冊觀察者:

image.png

[圖片上傳中扣癣。。憨降。(3)]

B. 屬性(keyPath)的值發(fā)送變化時父虑,收到通知,調(diào)用以下方法:

image.png

[圖片上傳中授药。士嚎。呜魄。(4)]

六、上代碼~:
1.新建項目莱衩,UI界面設(shè)計如下:第一個是便簽爵嗅,用于顯示num數(shù)值,關(guān)聯(lián)ViewController并命名為:label笨蚁;
第二個是按鈕睹晒,用于改變num的數(shù)值,關(guān)聯(lián)ViewController并命名為:changeNum括细。

image.png

[圖片上傳中伪很。。奋单。(5)]

2.模型創(chuàng)建【新建一個File锉试,選擇Cocoa Touch Class留凭,命名為“myKVO”斤吐,記得選擇Subclass of “NSObject”.】代碼如下:
(myKVO.h):

image.png

[圖片上傳中。那伐。贷笛。(6)]

(myKVO.m):

image.png

[圖片上傳中应又。。昨忆。(7)]

3.在ViewController中監(jiān)聽并響應(yīng)屬性改變丁频。
(ViewController.h):

image.png

[圖片上傳中。邑贴。席里。(8)]

(ViewController.m):

image.png

[圖片上傳中。拢驾。奖磁。(9)]

調(diào)試:便簽label初始化沒有數(shù)值,當(dāng)每次點擊按鈕后繁疤,label記錄的num隨之增加咖为,表明按鈕使屬性num增加的同時,KVO機制發(fā)送通知稠腊,并調(diào)用observeValueForKeyPath:方法使UI更新躁染。
七、拓展-->
1.與KVC的不同架忌?
KVC(鍵值編碼)吞彤,即Key-Value Coding,一個非正式的Protocol,使用字符串(鍵)訪問一個對象實例變量的機制饰恕。而不是通過調(diào)用Setter挠羔、Getter方法等 顯式的存取方式去訪問。
KVO(鍵值監(jiān)聽)埋嵌,即Key-Value Observing破加,它提供一種機制,當(dāng)指定的對象的屬性被修改后,對象就會接受到通知,前提是執(zhí)行了setter方法雹嗦、或者使用了 KVC賦值范舀。
2.和notification(通知)的區(qū)別?
notification比KVO多了發(fā)送通知的一步俐银。
兩者都是一對多尿背,但是對象之間直接的交互,notification明顯得多捶惜,需要notificationCenter來做為中間交互田藐。而KVO如我們介紹的,設(shè)置觀察者->處理屬性變化吱七,至于中間通知這一環(huán)汽久,則隱秘多了,只留一句“交由系統(tǒng)通知”踊餐,具體的可參照以上實現(xiàn)過程的剖析景醇。
notification的優(yōu)點是監(jiān)聽不局限于屬性的變化,還可以對多種多樣的狀態(tài)變化進行監(jiān)聽吝岭,監(jiān)聽范圍廣三痰,例如鍵盤、前后臺等系統(tǒng)通知的使用也更顯靈活方便窜管。
3.與delegate的不同散劫?
和delegate一樣,KVO和NSNotification的作用都是類與類之間的通信幕帆。但是與delegate不同的是:
這兩個都是負(fù)責(zé)發(fā)送接收通知获搏,剩下的事情由系統(tǒng)處理,所以不用返回值失乾;而delegate 則需要通信的對象通過變量(代理)聯(lián)系常熙;
delegate只是一對一,而這兩個可以一對多碱茁。
4.涉及技術(shù):
KVC/KVO實現(xiàn)的根本是Objective-C的動態(tài)性和runtime裸卫,以及訪問器方法的實現(xiàn);
總結(jié):
對比其他的回調(diào)方式纽竣,KVO機制的運用的實現(xiàn)墓贿,更多的由系統(tǒng)支持,相比notification、delegate等更簡潔些募壕,并且能夠提供觀察屬性的最新值以及原始值;但是相應(yīng)的在創(chuàng)建子類语盈、重寫方法等等方面的內(nèi)存消耗是很巨大的舱馅。所以對于兩個類之間的通信,我們可以根據(jù)實際開發(fā)的環(huán)境采用不同的方法刀荒,使得開發(fā)的項目更加簡潔實用代嗤。
另外需要注意的是,由于這種繼承方式的注入是在運行時而不是編譯時實現(xiàn)的缠借,如果給定的實例沒有觀察者干毅,那么KVO不會有任何開銷,因為此時根本就沒有KVO代碼存在泼返。但是即使沒有觀察者硝逢,委托和NSNotification還是得工作,這也是KVO此處零開銷觀察的優(yōu)勢绅喉。

作者:iOS開發(fā)攻城獅鏈接:http://www.reibang.com/p/78c9b8a3c303來源:簡書著作權(quán)歸作者所有渠鸽。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處柴罐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末徽缚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子革屠,更是在濱河造成了極大的恐慌凿试,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件似芝,死亡現(xiàn)場離奇詭異那婉,居然都是意外死亡,警方通過查閱死者的電腦和手機国觉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門吧恃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人麻诀,你說我怎么就攤上這事痕寓。” “怎么了蝇闭?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵呻率,是天一觀的道長。 經(jīng)常有香客問我呻引,道長礼仗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮元践,結(jié)果婚禮上韭脊,老公的妹妹穿的比我還像新娘。我一直安慰自己单旁,他們只是感情好沪羔,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著象浑,像睡著了一般蔫饰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上愉豺,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天篓吁,我揣著相機與錄音,去河邊找鬼蚪拦。 笑死杖剪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的外盯。 我是一名探鬼主播摘盆,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饱苟!你這毒婦竟也來了孩擂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤箱熬,失蹤者是張志新(化名)和其女友劉穎类垦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體城须,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蚤认,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了糕伐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砰琢。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖良瞧,靈堂內(nèi)的尸體忽然破棺而出陪汽,到底是詐尸還是另有隱情,我是刑警寧澤褥蚯,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布挚冤,位于F島的核電站,受9級特大地震影響赞庶,放射性物質(zhì)發(fā)生泄漏训挡。R本人自食惡果不足惜澳骤,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澜薄。 院中可真熱鬧为肮,春花似錦、人聲如沸肤京。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟆沫。三九已至,卻和暖如春温治,著一層夾襖步出監(jiān)牢的瞬間饭庞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工熬荆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舟山,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓卤恳,卻偏偏與公主長得像累盗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子突琳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容