KVO和KVC

全稱(chēng)
  • KVO: Key-Value-Observer
  • KVC: Key-Value-Coding

KVO的使用

使用過(guò)程
  • 監(jiān)聽(tīng)回調(diào)返回新值和舊值
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;

  • 添加監(jiān)聽(tīng)
    [被監(jiān)聽(tīng)的實(shí)例對(duì)象 addObserver:監(jiān)聽(tīng)器 forKeyPath:屬性 options:options context:nil]

  • 監(jiān)聽(tīng)接收事件
    - (void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionaryid> *)changecontext:(void*)context{ NSLog(@"%@--%@--%@",object,keyPath,change); }

  • 記得添加監(jiān)聽(tīng)和移除監(jiān)聽(tīng),需要配對(duì)使用

原理

測(cè)試類(lèi) Person

  1. 系統(tǒng)會(huì)生成NSKVONotifying_Person類(lèi),該類(lèi)繼承Person,并且將Person的isa指向NSKVONotifying_Person。

  2. NSKVONotifying_Person從寫(xiě)監(jiān)控屬性的setter方法,內(nèi)部調(diào)用_assetXXXValueAndNotify();
    _assetXXXValueAndNotify內(nèi)部實(shí)現(xiàn):

    2.1 - (void)willChangeValueForKey:(NSString *)key;

    2.2- (void)didChangeValueForKey:(NSString *)key;

    2.3 didChangeValueForKey里面調(diào)用 [super didChangeValueForKey]時(shí),會(huì)觸發(fā)回調(diào)方法
    - (void)observeValueForKeyPath:(NSString*)keyPathofObject: (id)objectchange:(NSDictionaryid> *)changecontext:(void*)context

    通知開(kāi)發(fā)者數(shù)據(jù)發(fā)生變化。

3.NSKVONotifying_Person內(nèi)部還會(huì)從寫(xiě) - (Class)class; 方法,目的是隱藏系統(tǒng)生成的類(lèi)。

4.如果需要手動(dòng)調(diào)用,只需要調(diào)用2個(gè)方法:
willChangeValueForKey
didChangeValueForKey
即可;
5.單純使用KVO,訪(fǎng)問(wèn)成員變量person -> age = 10;是不會(huì)觸發(fā)KVO監(jiān)聽(tīng)的。

KVC setValueForKey: 和setValueForKeyPath:

假如Person對(duì)象有個(gè)屬性叫age

setValueForKey
  • 可以對(duì)實(shí)例對(duì)象的某個(gè)屬性賦值
setValueForKeyPath:入?yún)⑹锹窂剑?/h5>
  • 可以對(duì)實(shí)例對(duì)象中的,某個(gè)對(duì)象的某個(gè)屬性,進(jìn)行賦值;例如入?yún)⒖梢允?person.data.num,就代表對(duì)person對(duì)象的data對(duì)象的num屬性進(jìn)行賦值

  • 可以訪(fǎng)問(wèn)對(duì)象的隱藏屬性

  • 可以求最大最小值,再也不用手動(dòng)遍歷數(shù)組求值了

    求最大值:[array valueForKeyPath:@"@max.self"]

使用KVC賦值

例如Person中有一個(gè)age屬性

  • 查找順序
    1.setAge:
    2._setAge:

  • 假如上面2個(gè)方法都沒(méi)有實(shí)現(xiàn),則系統(tǒng)會(huì)調(diào)用是否允許直接訪(fǎng)問(wèn)成員變量方法:
    + (BOOL)accessInstanceVariablesDirectly
    如果返回NO,則系統(tǒng)調(diào)用setValue:forUndefineKey,直接報(bào)NSUnknowKeyException異常;

  • 如果沒(méi)有setter方法,只有成員變量時(shí),并且+ (BOOL)accessInstanceVariablesDirectly返回YES,KVO同樣可以監(jiān)測(cè)到屬性值發(fā)生了改變;
    例如需要查找的屬性叫age,則查找順序如下

  1. _age
  2. _isAge
  3. age
  4. isAge

如果方法未找到,上面4個(gè)屬性也未找到,則會(huì)報(bào)上面的異常setValue:forUndefineKey

KVC取值 valueForKey: 和valueForKeyPath:

  • 方法查找順序
  1. getKey
  2. key
  3. isKey
  4. _key

如果方法未找到,則會(huì)調(diào)用系統(tǒng)方法+ (BOOL)accessInstanceVariablesDirectly判斷是否可以直接訪(fǎng)問(wèn)成員變量,如果是NO,則會(huì)報(bào)valueForUndefineKey,如果是YES,則會(huì)按如下順序查找成員變量:

  1. _key
  2. _isKey
  3. key
  4. isKey
最后編輯于
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 什么是KVO? KVO 全稱(chēng) Key Value Observing,是蘋(píng)果提供的一套事件通知機(jī)制。允許對(duì)象監(jiān)聽(tīng)另...
    薩繆閱讀 7,862評(píng)論 0 17
  • 問(wèn)題 iOS用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO?(KVO的本質(zhì)是什么?) 如何手動(dòng)觸發(fā)KVO ? 首先需要了解KVO...
    hjltony閱讀 624評(píng)論 0 2
  • 什么是KVO? KVO 全稱(chēng) Key Value Observing,是蘋(píng)果提供的一套事件通知機(jī)制。允許對(duì)象監(jiān)聽(tīng)另...
    祀夢(mèng)_閱讀 513評(píng)論 0 4
  • @[TOC](IOS底層(三) KVO底層實(shí)現(xiàn)原理 ) 一,KVO簡(jiǎn)述 KVO的全稱(chēng) Key-Value Obse...
    孔雨露閱讀 827評(píng)論 0 6
  • 首先來(lái)看看幾個(gè)定義: 編譯型語(yǔ)言:概念:需要編輯器將源代碼編譯成機(jī)器碼之后才能執(zhí)行的語(yǔ)言。一般分兩個(gè)步驟 編譯(c...
    hui8685291閱讀 1,478評(píng)論 0 0

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