手動 觸發(fā) kvo
過程如下:
- 重寫
automaticallyNotifiesObserversForKey
返回 NO - 非可變?nèi)萜鲗傩?在 set 中 添加方法
willChangeValueForKey
,didChangeValueForKey
- 可變?nèi)萜鲗傩愿鶕?jù) kvc 創(chuàng)建 代理對象拗窃,并在里面調(diào)用方法
willChange:valuesAtIndexes:forKey:
,didChange:valuesAtIndexes:forKey:
- kvo 響應(yīng)方法
observeValueForKeyPath:ofObject:change:context:.
具體過程
- 重新方法
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;
}
- 在屬性 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"];
}
- 在可變?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];
- observeValueForKeyPath 響應(yīng)
- change 參數(shù):這是一個字典里面包含的key 有
kind: NSKeyValueChange灌侣,跟willChangeValueForKey
中的保持一致
indexes: String, 元素變更的位置或者 range
new: 設(shè)值的新值
old: 之前的舊值
- change 參數(shù):這是一個字典里面包含的key 有