KVC:鍵-值編碼,使用字符串直接訪問對象的屬性。
KVO:鍵值觀察機制,它提供了觀察某一屬性變化的方法
KVC底層實現(xiàn)調用 :當一個對象調用setvalue方法時,方法內部會做以下操作:
1.檢查是否存在相應的keu的set方法,如果存在,就調用set方法。
2.如果set方法存在,就會查找與key相同名稱的并且?guī)聞澗€的成員屬性,如果有,則直接給成員屬性賦值。
3.如果沒有找到_key,就會查找相同名稱的屬性key,有就直接賦值
4.如果還是沒有找到,則調用valueForUNdefineKey:和setValue:forUndefinedKey:方法,這些方法的默認實現(xiàn)都是拋出異常,我們班可以根據(jù)需要重寫它們。
KVO的底層實現(xiàn):
KVO基于runtime機制實現(xiàn)。
使用了isa(isa-swizzling)混寫,當一個對象(假設是persong對象,person的類是MYPerson)的屬性值(假設person的age)發(fā)生改變的時候,系統(tǒng)會自動生成一個類,繼承自 MYPerson:NSKVONotifying_MYPerson,在這個類的setAge方法里面,調用[super setAge:age] [self willChangeValueForKey:@"age"]和[self didChangeValueForKey:@"age"],而這兩個方法內部會主動監(jiān)聽內部的-(void)observeValueForKeyPath這個方法。
想要看到NSKVONotifying-MYPerson很簡單,在self.person.age=20;這里打斷點,在調試區(qū)就能看到_person->NSObject->isa=(Class)NSKVONotifying—MYPerson.同時我么在self.persong=[[MYPerson alloc]init];后面打斷點,看到_person->NSObject->isa=(Class)MYPerson,由此可見,在添加監(jiān)聽之后,person類型已經由MYPerson被改變成NSKVONotifying_MYPerson.KVO
KVO的缺陷:KVO是一個對象能夠觀察另外一個對象的屬性的值,并且能夠發(fā)現(xiàn)值的變化。前兩種模式更加適合一個controller與任何其他的對象進行通訊,而KVO更加適合任何類型的對象偵聽另外一個任意對象的改變(這里也可以是controller,但一般不是controller)。這是一個對象與另外一個對象保持同步的一種方法,即當另外一個對象的狀態(tài)發(fā)生改變的時候,觀察對象馬上做出反應,它只能對屬性做出反應,而不會對方法或者動作做出反應。
優(yōu)點:
1.能夠提供一種簡單的方法實現(xiàn)兩個對象間的同步,例如:model和view之間的同步。
2.能夠對非我們創(chuàng)建的對象,即內部對象的狀態(tài)改變做出響應,而且不需要改變內部對象(SKD對象)的實現(xiàn)。
3.能夠提供觀察屬性的最新值以及先前值。
4.用key paths來觀察屬性,因此也可以觀察嵌套對象。
5.完成了對觀察對象的抽象,因為不需要額外的代碼來允許觀察值能夠被觀察。
缺點:
1.我們觀察的屬性必須使用strings來定義,因此編譯器不會出現(xiàn)警告以及檢查。
2.對屬性重構將導致我么你的觀察代碼不再可用。
3.復雜的if語句要求對象正在觀察對個值,這是因為所有的觀察代碼通過一個方法來指向。
4.當釋放觀察者的時候需要移除觀察者。