1霞篡、當(dāng)一個(gè)對(duì)象被觀察時(shí)歪今,runtime會(huì)動(dòng)態(tài)自動(dòng)創(chuàng)建繼承該對(duì)象的類,
2践美、并重寫被觀察對(duì)象的setter和getter方法洗贰,setter負(fù)責(zé)調(diào)用原setter并通知所有觀察對(duì)象值的改變;
3陨倡、 最后把該對(duì)象的指針指向這個(gè)創(chuàng)建的子類敛滋,對(duì)象就變成該子類的實(shí)例;
4兴革、 如何創(chuàng)建手動(dòng)觸發(fā)KVO矛缨,在setter方法里手動(dòng)實(shí)現(xiàn)
willChangeValueForKey 與 didChangeValueForKey
1. KVO是通過isa-swizzing的方法來實(shí)現(xiàn)的。就是比如B作為觀察者觀察A的屬性name時(shí)帖旨,在運(yùn)行時(shí)會(huì)動(dòng)態(tài)生成一個(gè)A的子類notify_A類,然后將A類的實(shí)例對(duì)象的isa指針指向notify_A這個(gè)子類灵妨,然后在子類中重寫的方法有三個(gè)
- (void) setName:(NSString*) name
{
willChangeValueForKey;
_name = name;
didChangeValueForKey;
}
2. 重寫了class方法解阅,返回的是原來的A類對(duì)象,這樣的話內(nèi)部再調(diào)用A類實(shí)例變量的其他方法時(shí)則不會(huì)發(fā)生問題泌霍。
class
{
return class_getSuperclass(object_getClass(self));
}
3. 重寫了delloc方法货抄,在合適的時(shí)候銷毀這個(gè)運(yùn)行時(shí)創(chuàng)建的類。
1.KVC與KVO的不同朱转?
KVC(鍵值編碼)蟹地,即Key-Value Coding,一個(gè)非正式的Protocol藤为,使用字符串(鍵)訪問一個(gè)對(duì)象實(shí)例變量的機(jī)制怪与。而不是通過調(diào)用Setter、Getter方法等顯式的存取方式去問缅疟。
KVO(鍵值監(jiān)聽)分别,即Key-Value Observing,它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后,對(duì)象就會(huì)接受到通知存淫,前提是執(zhí)行了setter方法耘斩、或者使用了KVC賦值。
2.和notification(通知)的區(qū)別桅咆?
notification比KVO多了發(fā)送通知的一步括授。兩者都是一對(duì)多,但是對(duì)象之間直接的交互,notification明顯得多荚虚,需要notificationCenter來做為中間交互薛夜。而KVO如我們介紹的,設(shè)置觀察者->處理屬性變化曲管,至于中間通知這一環(huán)却邓,則隱秘多了,只留一句“交由系統(tǒng)通知”院水,具體的可參照以上實(shí)現(xiàn)過程的剖析腊徙。
notification的優(yōu)點(diǎn)是監(jiān)聽不局限于屬性的變化,還可以對(duì)多種多樣的狀態(tài)變化進(jìn)行監(jiān)聽檬某,監(jiān)聽范圍廣撬腾,例如鍵盤、前后臺(tái)等系統(tǒng)通知的使用也更顯靈活方便恢恼。(參照通知機(jī)制第五節(jié)系統(tǒng)通知名稱內(nèi)容)
3.與delegate的不同民傻?
和delegate一樣,KVO和NSNotification的作用都是類與類之間的通信场斑。但是與delegate不同的是:
這兩個(gè)都是負(fù)責(zé)發(fā)送接收通知漓踢,剩下的事情由系統(tǒng)處理,所以不用返回值漏隐;而delegate 則需要通信的對(duì)象通過變量(代理)聯(lián)系喧半;
delegate一般是一對(duì)一,而這兩個(gè)可以一對(duì)多青责。
4.涉及技術(shù):
KVC/KVO實(shí)現(xiàn)的根本是Objective-C的動(dòng)態(tài)性和runtime挺据,以及訪問器方法的實(shí)現(xiàn);
總結(jié):
對(duì)比其他的回調(diào)方式脖隶,KVO機(jī)制的運(yùn)用的實(shí)現(xiàn)扁耐,更多的由系統(tǒng)支持,相比notification产阱、delegate等更簡潔些婉称,并且能夠提供觀察屬性的最新值以及原始值;但是相應(yīng)的在創(chuàng)建子類构蹬、重寫方法等等方面的內(nèi)存消耗是很巨大的酿矢。所以對(duì)于兩個(gè)類之間的通信,我們可以根據(jù)實(shí)際開發(fā)的環(huán)境采用不同的方法怎燥,使得開發(fā)的項(xiàng)目更加簡潔實(shí)用瘫筐。
另外需要注意的是,由于這種繼承方式的注入是在運(yùn)行時(shí)而不是編譯時(shí)實(shí)現(xiàn)的铐姚,如果給定的實(shí)例沒有觀察者策肝,那么KVO不會(huì)有任何開銷肛捍,因?yàn)榇藭r(shí)根本就沒有KVO代碼存在。但是即使沒有觀察者之众,委托和NSNotification還是得工作拙毫,這也是KVO此處零開銷觀察的優(yōu)勢。
異步:監(jiān)聽通知 主線程:發(fā)出通知 接收通知代碼在主線程
主線程:監(jiān)聽通知 異步:發(fā)出通知 接收通知代碼在異步
注意:在接收通知代碼中 可以加上主隊(duì)列任務(wù)
總結(jié):接收通知代碼 由 發(fā)出通知線程決定, KVO也一樣