使用KVO监听数组的变化
以前有个需求,需要监听数组长度的变化。使用KVO直接监听数组本身,由于数组地址并没有发生改变,所以并不能监听到。试了好多方法,都没有能够实现。知道最近听的一场公开课中,才掌握了正确的监听方法
先举个错误的例子
@interface ViewController () @property (nonatomic, strong) NSMutableArray *array; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self.array addObserver:self forKeyPath:@"count" options:(NSKeyValueObservingOptionNew) context:nil]; }
这样会直接报错,NSMutableArray 没有 count的 keyPath。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<__NSArrayM 0x282195770> addObserver:forKeyPath:options:context:] is not supported. Key path: count'
正确的打开方式是这样的,不多说废话,直接上代码
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self addObserver:self forKeyPath:NSStringFromSelector(@selector(array)) options:(NSKeyValueObservingOptionNew) context:nil];
}
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context {
/*
typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
NSKeyValueChangeSetting = 1,
NSKeyValueChangeInsertion = 2,
NSKeyValueChangeRemoval = 3,
NSKeyValueChangeReplacement = 4,
};
*/
//第一次触发是添加一条数据,kind为2,对应的是NSKeyValueChangeInsertion
/*
{
indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
kind = 2;
new = (
"NewData- 1"
);
}
*/
//第二次触发是修改一条数据,kind为4,对应的是NSKeyValueChangeReplacement
/*
{
indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
kind = 4;
new = (
"NewData- 2"
);
}
*/
//第三次次触发是删除一条数据,kind为3,对应的是NSKeyValueChangeRemoval
/*
{
indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
kind = 3;
}
*/
NSLog(@"我触发了");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
static NSInteger a = 0;
a++;
//这一步特别重要
NSMutableArray *tempArray = [self mutableArrayValueForKey:NSStringFromSelector(@selector(array))];
if (1 == a) {//插入一条
[tempArray addObject:[NSString stringWithFormat:@"NewData- %tu",a]];
} else if (2 == a) {//修改一条
tempArray[0] = [NSString stringWithFormat:@"NewData- %tu",a];
} else if (3 == a) {
[tempArray removeAllObjects];
}
}
- (NSMutableArray *)array {
if (!_array) {
_array = [NSMutableArray array];
}
return _array;
}
- (void)dealloc {
[self removeObserver:self forKeyPath:NSStringFromSelector(@selector(array))];
}
KVO三部曲,注册监听,实现代理方法,移除监听。
在监听数组变化时,需要特别注意,
NSMutableArray *tempArray = [self mutableArrayValueForKey:NSStringFromSelector(@selector(array))];
一定要使用该方法复制出一个数组,而不是使用数组本身进行操作。

浙公网安备 33010602011771号