KVO 和 KVC

一、KVO

KVO的是KeyValue Observe的縮寫,中文是鍵值觀察。這是一個(gè)典型的觀察者模式,利用它可以很容易使用實(shí)現(xiàn)視圖組件和數(shù)據(jù)模型的分離,當(dāng)數(shù)據(jù)模型的屬性值改變之后作為監(jiān)聽器的視圖組件就會(huì)被激發(fā),激發(fā)時(shí)就會(huì)回調(diào)監(jiān)聽器自身,在Objc中實(shí)現(xiàn)KVO則必須實(shí)現(xiàn)NSKeyValueObServing協(xié)議,不過幸運(yùn)的是NSObject已經(jīng)實(shí)現(xiàn)了該協(xié)議,因此幾乎所喲的NSObjectd對(duì)象都可以使用KVO。iOS中有個(gè)Notification的機(jī)制,也可以獲得通知,但這個(gè)機(jī)制需要有個(gè)Center,相比之下KVO更加簡潔而直接。

KVO的使用也很簡單,就是簡單的3步。

? ? ? 1.注冊(cè)需要觀察的對(duì)象的屬性addObserver:forKeyPath:options:context:

? ? ? 2.實(shí)現(xiàn)observeValueForKeyPath:ofObject:change:context:方法,這個(gè)方法當(dāng)觀察的屬性變化時(shí)會(huì)自動(dòng)調(diào)用

? ? ? 3.取消注冊(cè)觀察removeObserver:forKeyPath:context:

這里有兩種方式,一種是匹配keyPath,另一種是使用context

Demo:事列

A.注冊(cè)需要觀察的對(duì)象

- (void)viewDidLoad

{

? ? [super viewDidLoad];


? ? // 注冊(cè)監(jiān)聽

? ? [self.moveView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];


? ? self.p.name = @"小明";

? ? [self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:PersonAgeContext];

}

B.實(shí)現(xiàn)

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

? ? // 方式1.匹配keypath

? ? if ([keyPath isEqualToString:@"frame"]) {

? ? ? ? NSLog(@"self.moveView.y = %f", self.moveView.y);

? ? }


? ? // 方式2.上下文

? ? if (context == PersonAgeContext) {

? ? ? ? NSLog(@"%@%d歲了", self.p.name, self.p.age);

? ? }

}

C.移除監(jiān)聽

-(void)dealloc // ARC模式下

{

? ? [self.moveView removeObserver:self forKeyPath:@"frame"];


? ? [self.p removeObserver:self forKeyPath:@"age" context:PersonAgeContext];

}

KVO的 優(yōu)勢(shì) :

? ? ? ? 1.能夠提供一種簡單的方法實(shí)現(xiàn)兩個(gè)對(duì)象間的同步。例如:model和view之間同步;

? ? ? ? 2.能夠?qū)Ψ俏覀儎?chuàng)建的對(duì)象,即內(nèi)部對(duì)象的狀態(tài)改變作出響應(yīng),而且不需要改變內(nèi)部對(duì)象(SKD對(duì)象)的實(shí)現(xiàn);

? ? ? ? 3.能夠提供觀察的屬性的最新值以及先前值;

? ? ? ? 4.用key paths來觀察屬性,因此也可以觀察嵌套對(duì)象;

? ? ? ? 5.完成了對(duì)觀察對(duì)象的抽象,因?yàn)椴恍枰~外的代碼來允許觀察值能夠被觀察

? ? ? 缺點(diǎn) :

? ? ? ? 1.我們觀察的屬性必須使用strings來定義。因此在編譯器不會(huì)出現(xiàn)警告以及檢查;

? ? ? ? 2.對(duì)屬性重構(gòu)將導(dǎo)致我們的觀察代碼不再可用;

? ? ? ? 3.復(fù)雜的“IF”語句要求對(duì)象正在觀察多個(gè)值。這是因?yàn)樗械挠^察代碼通過一個(gè)方法來指向;

? ? ? ? 4.當(dāng)釋放觀察者時(shí)不需要移除觀察者。


二、KVC

KVC的常用方法:

- (id)valueForKey:(NSString *)key; -(void)setValue:(id)value forKey:(NSString *)key;

valueForKey的方法根據(jù)key的值讀取對(duì)象的屬性,setValue:forKey:是根據(jù)key的值來寫對(duì)象的屬性。

注意:

(1). key的值必須正確,如果拼寫錯(cuò)誤,會(huì)出現(xiàn)異常

(2). 當(dāng)key的值是沒有定義的,valueForUndefinedKey:這個(gè)方法會(huì)被調(diào)用,如果你自己寫了這個(gè)方法,key的值出錯(cuò)就會(huì)調(diào)用到這里來

(3). 因?yàn)轭恔ey反復(fù)嵌套,所以有個(gè)keyPath的概念,keyPath就是用.號(hào)來把一個(gè)一個(gè)key鏈接起來,這樣就可以根據(jù)這個(gè)路徑訪問下去

(4). NSArray/NSSet等都支持KVC


KVC過程講解:

以?[object setValue:@"134567" forKey:@"uid"];為例子,來探究KVC的實(shí)現(xiàn)過程

第一步:搜索

1、首先搜索setKey:方法.(key指成員變量名, 首字母大寫)

2、上面的setter方法沒找到, 如果類方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey,key, iskey的順序搜索成員名.(NSKeyValueCodingCatogery中實(shí)現(xiàn)的類方法, 默認(rèn)實(shí)現(xiàn)為返回YES)

3、如果沒有找到成員變量, 調(diào)用setValue:forUnderfinedKey:

第二步:編譯器處理

被編譯器處理后:

// 首先找到對(duì)應(yīng)sel

SEL sel = sel_get_uid("setValue:forKey:");

// 根據(jù)object->isa找到sel對(duì)應(yīng)的IMP實(shí)現(xiàn)指針

IMP method = objc_msg_lookup (object->isa,sel);

// 調(diào)用指針完成KVC賦值

method(object, sel, @"134567", @"uid");

解釋:

1.先根據(jù)方法名通過C函數(shù)sel_get_uid拿到選擇子sel

2.使用C函數(shù)objc_msg_lookup通過對(duì)象指針,選擇子獲取函數(shù)實(shí)現(xiàn)指針

3. 調(diào)用C函數(shù)method(object, sel, @"134567", @"uid"),實(shí)現(xiàn)KVC賦值


引申:setValue和setObject區(qū)別

setObject:ForKey: 是NSMutableDictionary特有的;setValue:ForKey:是KVC的主要方法

setobject中的key和value可以為除了nil外的任何對(duì)象

setValue中的key只能為字符串 value可以為nil也可以為空對(duì)象[NSNull null]以及全部對(duì)象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Key Value Observing(KVO)鍵值觀察,它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后,則對(duì)象就會(huì)接...
    小小土豆dev閱讀 287評(píng)論 0 5
  • 【原創(chuàng)博文,轉(zhuǎn)載請(qǐng)注明出處!】之前做iOS開發(fā)的時(shí)候經(jīng)常使用KVO來監(jiān)聽對(duì)象屬性值的變化去執(zhí)行一些操作,但是從未思...
    RephontilZhou閱讀 1,161評(píng)論 1 9
  • 一. KVO是鍵值觀察,是Objective-C對(duì)觀察者模式的實(shí)現(xiàn),每次當(dāng)被觀察者對(duì)象的某個(gè)屬性值發(fā)生改變時(shí),注冊(cè)...
    魂一飛閱讀 339評(píng)論 0 0
  • KVC KVC定義 KVC(Key-value coding)鍵值編碼,就是指iOS的開發(fā)中,可以允許開發(fā)者通過K...
    戀空K閱讀 830評(píng)論 0 2
  • 今天青石的票圈出鏡率最高的,莫過于張藝謀的新片終于定檔了。 一張滿溢著水墨風(fēng)的海報(bào)一次次的出現(xiàn)在票圈里,也就是老謀...
    青石電影閱讀 10,858評(píng)論 1 2

友情鏈接更多精彩內(nèi)容