面向对象3-键值编码(KVC)和键值监听(KVO)
2016-02-20 10:18
477 查看
键值编码(KVC)和键值监听(KVO)
KVC
@interface MyUser:NSObject @property (nonatomic, copy) NSString* name; @end main() { @autoreleasepool { MyUser* user = [[MyUser allopc] init]; //用KVC方式为属性赋值 [user setValue:@"孙悟空" forKey:@"name"]; //用KVC方式获取属性值 NSLog(@"user's name is: %@", [user valueForKey:@"name"]); } }
KVC两种方法:
setValue:属性值 forKey:属性名 : 用于赋值
valueForKey:属性名 : 获取属性值
处理不存在的key
当key不存在时,会自动调用 setValue:forUndefinedKey: 和 valueForUndefinedKey: 由于这两个方法默认的方法体会引发 ‘NSUnknownKeyException’ 异常,并结束程序,一般情况下需要重写这两个方法。- (void) setValue: (id) value forUndefinedKey: (id) key { NSLog(@"the key: (%@) being set does not exist!", key); NSlog(@"the value being set is: %@", value); } - (void) valueForUndefinedKey: (id) key { NSLog(@"the key: (%@) being get does exist!", key); }
处理nil值
非chat、NSString*类型的属性,不能赋予 nil ,可通过重写 NSObject 的 setNilValueForKey: 方法来将不合理的 nil 转化成合理的其他值//省略代码:定义类接口和实现部分,分别呢含有 NSString* name 和 int price 属性,并为两个属性赋值 nil //一下为重写 NSObject 的setNilValueForKey: 方法 - (void) setNilValueForKey: (id) key { //当尝试为 price 属性赋值 nil 时,执行以下语句 if([key isEqualToString:@"price"]) { //将 price 赋值为0 price = 0; } else { //调回父类的 setNilValueForKey: 方法来赋值 nil [super setNilValueForKey: key]; } }
Key路径
KVC可对复合属性进行操作,所谓复合属性即:将已存在的类A作为本类B的属性,这样在本类B中亦可调用属性类A的属性(B.A.property)#import <Foundation/Foundation.h> #import "MyItem.h" @interface MyItem: NSObject @property NSString* name; @property int price; @end @interface MyOrder: NSObject //将 MyItem* 类对象作为属性 @property MyItem* item; @end //实现部分忽略,自行编写 int main(int argh, char * argv[]) { @autoreleasepool { //创建MyOrder对象 MyOrder* order = [[MyOrder alloc] init]; //用KVC方式赋值 [order setValue:[[MyItem alloc] init] forKey:@"item"]; [order setValue:@"张三" forKey:@"item.name"]; [roder setValue:[NSNumber numberWithInt:25] forKey:@"item.price"]; //用KVC方式访问属性值 NSLog(@"name is: %@",[order calueForKey:@"item.name"]); } }
键值监听(KVO)
应用场景:数据模型组件中有数据发生修改,需视图组件实时更新addObserver:forKeyPath:options:context: 注册监听器
removeObserver:forKeyPath: 删除监听器
removeObserver:foKea:contact: 删除监听器
//接口部分省略,自行编写 @implementation MyItemView @snythesize item = _item; - (void) setItem:(MyItem*) item //自定义 setItem: 方法 { self->_item = item; //为item添加监听器,监听 name 属性, item为类属性,name为复合属性 [self.item addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew Context:nil]; } //重写 observerValueForKeyPath: 方法,这样监听的数据模型发生改变时,就会回调监听器的该方法 - (void) observerValueForKeyPath:(NSString*) keyPath ofObject:(id) object chat:(NSDictionary*) change context:(void*)context { NSLog(@"--调用了 observerValueForKeyPath: 方法--"); NSLog(@"对象(%@)的属性(%@)被修改为 %@,被修改的上下文是 %@",object, keyPath, [hange objectForKey:@"new"], context); } - (void) dealloc { //删除监听器 [self.item removeObserver:self forKeyPath:@"name"]; } @end
调用代码:
MyItem* item = [[MyItem alloc] init]; item.name = @"张三"; //由于视图组件没有创建 4000 对象,所以不会显示信息 MyItemView* itemView = [[MyItemView alloc] init]; [itemView showItemInfo]; //showItemInfo为输出信息方法,之前代码中省略掉了 item.name = @"李四"; //视图组件已创建对象,name属性被监听且值被更改,激发了监听器会输出结果
输出结果:
item name is: 张三 --调用了observerValueForKeyPath: 方法-- 对象(<MyItem: 0x7faa02309780>)的属性(name)被修改为 李四,被修改的上下文是 (null)
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#中面向对象编程机制之多态学习笔记
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- ASP编码必备的8条原则
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- C#面向对象特征的具体实现及作用详解
- C# 面向对象的基本原则
- 浅谈对c# 面向对象的理解
- XML指南——XML编码
- C#中字符串编码处理
- ExtJS中文乱码之GBK格式编码解决方案及代码