手動 觸發(fā) kvo

手動 觸發(fā) kvo


過程如下:

  1. 重寫automaticallyNotifiesObserversForKey 返回 NO
  2. 非可變?nèi)萜鲗傩?在 set 中 添加方法 willChangeValueForKey,didChangeValueForKey
  3. 可變?nèi)萜鲗傩愿鶕?jù) kvc 創(chuàng)建 代理對象拗窃,并在里面調(diào)用方法 willChange:valuesAtIndexes:forKey:, didChange:valuesAtIndexes:forKey:
  4. kvo 響應(yīng)方法 observeValueForKeyPath:ofObject:change:context:.

具體過程

  1. 重新方法 automaticallyNotifiesObserversForKey , 對需要手動控制 kvo 的 key 返回 NO
    我們把 屬性 name, number, arr, mutableArr 都設(shè)為手動觸發(fā) kvo
    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
        BOOL automatic = NO;
        if ([key isEqualToString:@"name"]) {
            automatic = NO;
        }else if ([key isEqualToString:@"number"]){
            automatic = NO;
        }else if ([key isEqualToString:@"arr"]){
            automatic = NO;
        }else if ([key isEqualToString:@"mutableArr"]){
            automatic = NO;
        }else {
            automatic = [super automaticallyNotifiesObserversForKey:key];
        }
        return automatic;
    }

  1. 在屬性 set 方法中手動觸發(fā) kvo, willChangeValueForKey, didChangeValueForKey
    // 手動改管理 kvo 觸發(fā)可训,有個明顯的好處,就是,我們在不需要觸發(fā)kvo時可以很容易的停止觸發(fā),如下
    // 當 name 在設(shè)值 前和 設(shè)值后 是一樣的比如都是 王小小,我們就可以不觸發(fā)kvo
    // 如果是 自動 kvo 就無法達到這樣的控制效果。
    - (void)setName:(NSString *)name{
    if (![_name isEqualToString:name]) {
        [self willChangeValueForKey:@"name"];
        _name = name;
        [self didChangeValueForKey:@"name"];
        }
    }
    // 設(shè)值 kvo 觸發(fā)條件特石, 只有當 bunber > 10 的時候,才會觸發(fā) kvo鳖链。
    - (void)setNumber:(int)number{
        if (number>10) {
            [self willChangeValueForKey:@"number"];
            _number = number;
            [self didChangeValueForKey:@"number"];
        }
    }

    - (void)setArr:(NSArray<NSString *> *)arr{
        [self willChangeValueForKey:@"arr"];
        _arr = arr;
        [self didChangeValueForKey:@"arr"];
    }
  1. 在可變?nèi)萜髦杏|發(fā) kvo姆蘸, 結(jié)合 kvc 可變?nèi)萜鞔韺ο髣?chuàng)建。
    需要實現(xiàn)一對刪除和插入的方法, 并在這些方法中調(diào)用方法 willChange:valuesAtIndexes:forKey:, didChange:valuesAtIndexes:forKey:
        // 可變?nèi)萜魈砑邮謩觡vo芙委,可變?nèi)萜鲀?nèi)部元素發(fā)生添加逞敷,移除,替換時觸發(fā)kvo
        // 插入單個 元素
        - (void)insertObject:(NSString *)object inMutableArrAtIndex:(NSUInteger)index{
            [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
            [_mutableArr insertObject:object atIndex:index];
             [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
        }

        // 刪除 單個元素
        - (void)removeObjectFromMutableArrAtIndex:(NSUInteger)index{
            [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
            [_mutableArr removeObjectAtIndex:index];
            [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
        }
        // 插入 多個元素
        - (void)insertMutableArr:(NSArray *)array atIndexes:(NSIndexSet *)indexes{
            [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:@"mutableArr"];
            [_mutableArr insertObjects:array atIndexes:indexes];
            [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:@"mutableArr"];
        }
        // 刪除多個元素
        - (void)removeMutableArrAtIndexes:(NSIndexSet *)indexes{
            [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"mutableArr"];
            [_mutableArr removeObjectsAtIndexes:indexes];
            [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:@"mutableArr"];
        }
        // 替換 單個
        - (void)replaceObjectInMutableArrAtIndex:(NSUInteger)index withObject:(id)object{
            [self willChange:NSKeyValueChangeReplacement valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
            [_mutableArr replaceObjectAtIndex:index withObject:object];
            [self didChange:NSKeyValueChangeReplacement valuesAtIndexes:[NSIndexSet indexSetWithIndex:index] forKey:@"mutableArr"];
        }
        // 替換 多個
        - (void)replaceMutableArrAtIndexes:(NSIndexSet *)indexes withMutableArr:(NSArray *)array{
            [self willChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:@"mutableArr"];
            [_mutableArr replaceObjectsAtIndexes:indexes withObjects:array];
            [self didChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:@"mutableArr"];
        }

外部調(diào)用

    // 必須通過 kvc 拿到 屬性
    NSMutableArray *mutableArr = [obj mutableArrayValueForKey:@"mutableArr"];
    // 添加一個元素
    [mutableArr addObject:@"100"];
    // 刪除一個元素
    [mutableArr removeObjectAtIndex:0];
    // 添加多個元素
    [mutableArr addObjectsFromArray:@[@"90",@"91"]];
    // 刪除多個元素
    [mutableArr removeObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]];
    // 替換一個元素
    [mutableArr replaceObjectAtIndex:0 withObject:@"替換"];
    // 替換多個元素
    NSArray *objs = @[@"替換: 1",@"替換: 2"];
    [mutableArr replaceObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, objs.count)] withObjects:objs];
  1. observeValueForKeyPath 響應(yīng)
    • change 參數(shù):這是一個字典里面包含的key 有
      kind: NSKeyValueChange灌侣,跟 willChangeValueForKey 中的保持一致
      indexes: String, 元素變更的位置或者 range
      new: 設(shè)值的新值
      old: 之前的舊值
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末推捐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子顶瞳,更是在濱河造成了極大的恐慌玖姑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慨菱,死亡現(xiàn)場離奇詭異焰络,居然都是意外死亡,警方通過查閱死者的電腦和手機符喝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門闪彼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人协饲,你說我怎么就攤上這事畏腕。” “怎么了茉稠?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵描馅,是天一觀的道長。 經(jīng)常有香客問我而线,道長铭污,這世上最難降的妖魔是什么恋日? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮嘹狞,結(jié)果婚禮上岂膳,老公的妹妹穿的比我還像新娘。我一直安慰自己磅网,他們只是感情好谈截,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涧偷,像睡著了一般簸喂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上燎潮,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天娘赴,我揣著相機與錄音,去河邊找鬼跟啤。 笑死,一個胖子當著我的面吹牛唉锌,可吹牛的內(nèi)容都是我干的隅肥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼袄简,長吁一口氣:“原來是場噩夢啊……” “哼腥放!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绿语,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤秃症,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吕粹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體种柑,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年匹耕,在試婚紗的時候發(fā)現(xiàn)自己被綠了聚请。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡稳其,死狀恐怖驶赏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情既鞠,我是刑警寧澤煤傍,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站嘱蛋,受9級特大地震影響蚯姆,放射性物質(zhì)發(fā)生泄漏五续。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一蒋失、第九天 我趴在偏房一處隱蔽的房頂上張望返帕。 院中可真熱鬧,春花似錦篙挽、人聲如沸荆萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽链韭。三九已至,卻和暖如春煮落,著一層夾襖步出監(jiān)牢的瞬間敞峭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工蝉仇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留旋讹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓轿衔,卻偏偏與公主長得像沉迹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子害驹,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355