KVO 深入學習


KVO 的基本調用

1. 在需要監(jiān)聽的類中公你,加入以下代碼
[car addObserver:self 
      forKeyPath:@"要監(jiān)聽的屬性" 
         options:NSKeyValueObservingOptionNew context:nil];
(_本例中 car 是需要被監(jiān)聽的一個類的實例_)

2. 添加一個屬性監(jiān)聽的回調函數
- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change 
                       context:(void *)context {
    // 如果屬性值有改動踊淳,執(zhí)行該函數
    if([keyPath isEqualToString:@"要監(jiān)聽的屬性"]) {
    }
}

3. 當類被銷毀時,需要取消監(jiān)聽
- (void)dealloc {
    [self removeObserver:self forKeyPath:@"要監(jiān)聽的屬性"];
}

  • NSKeyValueObservingOptions說明:
    • NSKeyValueObservingOptionNew:在回調函數中的change對象中會返回該屬性修改后的值陕靠。
    • NSKeyValueObservingOptionOld:在回調函數中的change對象中會返回該屬性修改前的值迂尝。
    • NSKeyValueObservingOptionInitial:在剛開始設置addObserver:監(jiān)聽的時候,就默認觸發(fā)一次回調函數懦傍。
    • NSKeyValueObservingOptionPrior:當被監(jiān)聽的屬性修改的前后都會觸發(fā)一次回調函數雹舀。
  • (NSDictionary<NSKeyValueChangeKey,id> *)change說明:
    • 被監(jiān)聽的屬性名為 Key,以 NSKeyValueObservingOptions 配置而返回的屬性值為 Value粗俱。
    • kind的 Value 有以下4種意思
      • NSKeyValueChange = 1:值改變
      • NSKeyValueChangeInsertion = 2:插入新值(集合類)
      • NSKeyValueChangeRemoval = 3:移除值(集合類)
      • NSKeyValueChangeReplacement = 4:替換集合類中的值

如果自定義 KVO说榆?

一般情況下,只要我們按上面的步驟設置好寸认,則默認情況下只要有值改變則會自動觸發(fā)回調函數签财,如果我們想自定義的觸發(fā)的條件,可按以下步驟進行設置:

1. 在被監(jiān)聽的類中偏塞,將需要自定義的屬性設置為不自動觸發(fā)監(jiān)聽(在本例中就是上面提到的 Car 類)唱蒸。
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if([key isEqualToString:@"自定義的屬性"]) {
        return NO;
    }
    // 默認為自動觸發(fā)
    return YES;
}

2. 在需要手動觸發(fā)的函數中,寫入以下邏輯:
- (void)buttonAction:(UIButton *)sender {
    [self.car willChangeValueForKey:@"name"];
    self.car.name = @"要更新的值";
    [self.car didChangeValueForKey:@"name"];
}

按該步驟就能自定義觸發(fā)值的監(jiān)聽灸叼。


KVO 監(jiān)聽多個屬性的優(yōu)化


* 當我們想監(jiān)聽多個屬性的時候神汹,一般情況下會寫成以下方式:
[car addObserver:self forKeyPath:@"屬性 1" 
                         options:NSKeyValueObservingOptionNew context:nil];
[car addObserver:self forKeyPath:@"屬性 2" 
                          options:NSKeyValueObservingOptionNew context:nil];
[car addObserver:self forKeyPath:@"屬性 3" 
                          options:NSKeyValueObservingOptionNew context:nil];

* 為了減少代碼的冗余,我們可以在被監(jiān)聽的類里面古今,使用以下方式替換上面的代碼:
 - 監(jiān)聽類中:
  [car addObserver:self forKeyPath:@"屬性" 
                           options:NSKeyValueObservingOptionNew context:nil];

 - 被監(jiān)聽的類里面:
  + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key  {
    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
    if([key isEqualToString:@"屬性名"]) {
        NSArray *arr = @[@"屬性 1",@"屬性 2",@"屬性 3"];
        keyPaths = [keyPaths setByAddingObjectsFromArray:arr];
    }
    return keyPaths
}

KVO 實現原理

  1. 其實當我們在執(zhí)行 addObserver 監(jiān)聽方法的時候屁魏,就是將被監(jiān)聽的實例(car)的屬性 set 方法進行了重寫。
  2. 具體的實現方式就是通過 runtime 機制捉腥,創(chuàng)建了一個中間類氓拼,該類是原類的子類;并且修改 isa指針抵碟,指向這個中間類桃漾,這樣通過 OC 的消息轉發(fā)機制,首先就會執(zhí)行中間類的 set 方法拟逮,通過這種方式撬统,就可以在中間類的 set 方法中去執(zhí)行 willChangeValueForKeydidChangeValueForKey方法,同時修改屬性的值敦迄。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末恋追,一起剝皮案震驚了整個濱河市粒竖,隨后出現的幾起案子,更是在濱河造成了極大的恐慌几于,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沿后,死亡現場離奇詭異沿彭,居然都是意外死亡,警方通過查閱死者的電腦和手機尖滚,發(fā)現死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門喉刘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人漆弄,你說我怎么就攤上這事睦裳。” “怎么了撼唾?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵廉邑,是天一觀的道長。 經常有香客問我倒谷,道長蛛蒙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任渤愁,我火速辦了婚禮牵祟,結果婚禮上,老公的妹妹穿的比我還像新娘抖格。我一直安慰自己诺苹,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布雹拄。 她就那樣靜靜地躺著收奔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪办桨。 梳的紋絲不亂的頭發(fā)上筹淫,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音呢撞,去河邊找鬼损姜。 笑死,一個胖子當著我的面吹牛殊霞,可吹牛的內容都是我干的摧阅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼绷蹲,長吁一口氣:“原來是場噩夢啊……” “哼棒卷!你這毒婦竟也來了顾孽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤比规,失蹤者是張志新(化名)和其女友劉穎若厚,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體蜒什,經...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡测秸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了灾常。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霎冯。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钞瀑,靈堂內的尸體忽然破棺而出沈撞,到底是詐尸還是另有隱情,我是刑警寧澤雕什,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布缠俺,位于F島的核電站,受9級特大地震影響监徘,放射性物質發(fā)生泄漏晋修。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一凰盔、第九天 我趴在偏房一處隱蔽的房頂上張望墓卦。 院中可真熱鬧,春花似錦户敬、人聲如沸落剪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忠怖。三九已至,卻和暖如春抄瑟,著一層夾襖步出監(jiān)牢的瞬間凡泣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工皮假, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鞋拟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓惹资,卻偏偏與公主長得像贺纲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子褪测,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355