知識點(diǎn)總結(jié)中,如有幸被您觀看,更有可能看到不足,期待指出交流
前言
繼續(xù)學(xué)習(xí)中.....
KVC的底層實(shí)現(xiàn)
當(dāng)一個(gè)對象調(diào)用serValue方法時(shí),方法內(nèi)部會做下面的操作:
- 檢查是否存在相同的key的set方法,如果不存在,就調(diào)用set方法
- 如果set方法不存在,就會查找與key相同名稱并且?guī)聞澗€的成員屬性.如果有,則直接給成員屬性賦值.
- 如果沒有找到_key,就會查找相同名稱的屬性key,如果有就直接賦值
- 如果還沒有找到,則調(diào)用
valueForUndefinedKey:
setValue:forUnderfinedKey:
這些方法的默認(rèn)實(shí)現(xiàn)都是拋出異常,我們可以根據(jù)需要重寫他們.
KVO的底層實(shí)現(xiàn)
- KVO基于runtime機(jī)制實(shí)現(xiàn)
- 使用 isa 混寫 (isa-swizzling), 當(dāng)一個(gè)對象(假設(shè)person對象,person的類是MYperson) 的屬性值(假設(shè)person的age)發(fā)生改變時(shí),系統(tǒng)會自動生成一個(gè)類,繼承自MYPerson:NSKVONotifying_MYPerson,在這個(gè)類的setAge方法里面,調(diào)用
[super setAge:age]
[self willChangeValueForKey:@"age"]
[self didChangeValueForKey:@"age"]
下面這倆個(gè)方法內(nèi)部會主動調(diào)用監(jiān)聽者內(nèi)部的
-(void)observeValueForKeyPath
- 想要看到 NSKVONotifying_MYPerson 很簡單, 在self.person.age = 20; 這里打斷點(diǎn),在調(diào)試區(qū)域就能看到
_person->NSObject-isa=(Class)MYPerson
由此可見,person類型已經(jīng)由MYperson被改變成NSKVONotifing_MYperson
什么是KVO和KVC
KVC: 鍵值編碼,使用字符串直接訪問對象的屬性
KVO: 鍵值觀察機(jī)制,它提供了觀察某一屬性變化的方法
KVO的缺陷
KVO是一個(gè)對象能夠觀察另一個(gè)對象的屬性的值,并且能夠發(fā)現(xiàn)值的變化.block和代理,兩種模式更加適合一個(gè)Controller與任何其他的對象進(jìn)行通信.而KVO更加適合任何類型的對象監(jiān)聽另外一個(gè)任意對象(這里也可以是Controller,但一般不是Controller).這個(gè)一個(gè)對象與另外一個(gè)對象保持同步的一種方法,即單另外一種對象的狀態(tài)翻身改變時(shí),觀察對象馬上做出反應(yīng).它只能用來對屬性做出反應(yīng),而不會用來對方法或者動作做出反應(yīng).
優(yōu)點(diǎn):
- 能夠提供一種簡單的方法實(shí)現(xiàn)倆個(gè)對象間的同步,列如model和View之間的同步
- 能夠?qū)Ψ俏覀儎?chuàng)建的對象,即內(nèi)部對象的狀態(tài)改變做出相應(yīng),而且不需要改變內(nèi)部對象(SKD對象)的實(shí)現(xiàn)
- 能夠提供觀察的屬性的最新值以及先前值
- 用 key paths 來觀察屬性, 因此也可以觀察嵌套對象
- 完成了對觀察對象的都想,因?yàn)椴恍枰~外的代碼來允許鍵值被觀察
確定: - 我們觀察的屬性必須使用string來定義.因此編譯器不會出現(xiàn)警告以及檢查
- 對屬性重構(gòu)導(dǎo)致我們的觀察代碼不可再用
- 復(fù)雜的"IF"語句要求對象正在觀察多個(gè)值,這是因?yàn)樗械挠^察代碼通過一個(gè)方法來指向
- 當(dāng)釋放觀察者時(shí)需要移除觀察者