标签:
KVO与KVC详解
由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby、Python的动态特性,例如动态类型、动态加载、动态绑定等。今天我们着重介绍ObjC中的键值编码(KVC)、键值监听(KVO)特性:
我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象。其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Value Coding(简称KVC)。
KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:
我们知道在WPF、Silverlight中都有一种双向绑定机制,如果数据模型修改了之后会立即反映到UI视图上,类似的还有如今比较流行的基于MVVM设计模式的前端框架,例如Knockout.js。其实在ObjC中原生就支持这种机制,它叫做Key Value Observing(简称KVO)。KVO其实是一种观察者模式,利用它可以很容易实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器的视图组件就会被激发,激发时就会回调监听器自身。在ObjC中要实现KVO则必须实现NSKeyValueObServing协议,不过幸运的是NSObject已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。
在ObjC中使用KVO操作常用的方法如下:
KVO的使用步骤也比较简单:
/*********************************KVC/KVO*******************************************/
KVC
kvc在实际开发中使用最多的地方一般有两个
字典转模型:
1 #pragma mark 简单字典转模型 2 NSDictionary *dict = @{ 3 @"name" : @"jack", 4 @"money" : @"20.7", 5 }; 6 7 [p setValuesForKeysWithDictionary:dict]; 8 NSLog(@"name = %@, money = %f", p.name, p.money); 9 10 #pragma mark 复杂模型 11 NSDictionary *dict = @{ 12 @"name" : @"jack", 13 @"money" : @"20.7", 14 @"dog" : @{ 15 @"name" : @"wangcai", 16 @"price" : @"10.8" 17 }, 18 @"books" : @[ 19 @{ 20 @"name" : @"5分钟突破iOS开发", 21 @"price" : @"19.8" 22 }, 23 @{ 24 @"name" : @"3分钟突破iOS开发", 25 @"price" : @"24.8" 26 }, 27 @{ 28 @"name" : @"1分钟突破iOS开发", 29 @"price" : @"29.8" 30 } 31 ] 32 }; 33 [p setValuesForKeysWithDictionary:dict]; 34 NSLog(@"%@", p); 35 }
设置属性的值:
1 #pragma mark 单个值 2 p.name = @"lnj"; 3 p.money = 99.8; 4 5 [p setValue:@"lnj" forKey:@"name"]; 6 [p setValue:@(99.8) forKey:@"money"]; 7 NSLog(@"name = %@, money = %f", p.name, p.money); 8 9 #pragma mark 多层赋值 10 11 p.dog = [XMGDog new]; 12 p.dog.name = @"wangcai"; 13 p.dog.price = 998; 14 15 [p.dog setValue:@"wangcai" forKey:@"name"]; 16 [p.dog setValue:@(998) forKey:@"price"]; 17 18 [p setValue:@"wangcai" forKeyPath:@"dog.name"]; 19 [p setValue:@(998) forKeyPath:@"dog.price"]; 20 NSLog(@"name = %@, price = %f", p.dog.name, p.dog.price); 21 22 #pragma mark 私有属性 23 24 [p setValue:@"lnj" forKeyPath:@"_name"]; 25 [p setValue:@(30) forKeyPath:@"_age"]; 26 27 NSLog(@"name = %@", p.name); 28 [p say];
KVO
1:创建一个对象
1 iCocos *stu = [[iCocos alloc] init]; 2
2:注册指定Key路径的监听器,并且修改相应的属性
1 [stu addObserver:self forKeyPath:@"score" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; 2 3 stu.score = 90; 4 5 stu.score = 100;
3:删除指定Key路径的监听器
1 #warning 注意只有调用set方法修改才能监听到 2 内部实现原理是: 系统会自动给我们生成一个子类, 然后重写子类的set方法, 在set方法中通知监听 3 stu->_score = 250; 4 [stu removeObserver:self forKeyPath:@"score"];
4:回调监听
1 - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context 2 { 3 NSLog(@"keyPath = %@, obj = %@, change = %@, context = %@", keyPath, object, change, context); 4 }
KVO内部实现机制:
系统会自动给我们生成一个子类, 然后重写子类的set方法, 在set方法中通知监听
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4644079.html