面向对象(键值编码(KVC)与键值监听(KVO))
2016-01-13 16:31
423 查看
面向对象(键值编码(KVC)与键值监听(KVO))
简单的KVC
最基本的KVC由NSKeyValueCoding协议提供支持,最基本的操作属性的两个方法如下- setValue:属性值forKey:属性名 :为指定属性设置值。 - valueForKey:属性名:获取指定属性值
在KVC编程方式中,无论调用
setValue:forKey:方法,还是调用
valueForKey:方法,都是通过NSString对象来指定被操作属性的,其中forKey标签用于传入属性名。
对于”setValue:属性值 forKey@”name”;”代码,底层的执行机制如下。
1. 程序优先考虑调用"setName:属性值;"代码通过setter方法完成设置。 2. 如果该类没有setName:方法,那么KVC机制会搜索该类中名为_name的成员变量,无论该成员变量实在类接口部分定义,还是在 类实现部分定义,也无论用哪个访问控制符修饰,这条KVC代码底层实际就是_name成员变量赋值。 3. 如果该类既没有setName:方法,也没有定义_name成员变量,那么KVC机制会搜索该类中名为name的成员变量,无论该成员变量 是在类接口部分定义,还是在类实现部分定义,也无论用哪个访问控制符修饰,这条KVC代码底层实际上就是对name成员变量赋值。 4. 如果上面3步都没有找到,那么系统将会执行该对象的setValue:forUndefinedKey:方法(其实就是一个异常)
对于”valueforKey@”name”;”代码,底层的执行机制如下
1. 程序优先考虑调用"name;"代码来获取该getter方法的返回值。 2. 如果该类没有name方法,那么KVC机制会搜索该类中名为_name的成员变量,无论该成员变量实在类接口部分定义还是在类实现部 分定义,也无论调用哪个访问控制符修饰,这条KVC代码底层实际上就是返回_name成员变量的值。 3. 如果该类既没有name方法,也没有定义_name成员变量,那么KVC机制会搜索该类中名为name的成员变量,无论该成员变量实在类 接口部分定义还是在类实现部分定义,也无论调用哪个访问控制符修饰,这条KVC代码底层实际上就是返回name成员变量的值。 4. 如果上面3步都没有找到,那么系统将会执行该对象的valueForUndefinedKey:方法。(其实就是一个异常)
处理不存在的key
Objective-C并不存在绝对隐藏的方法,即使一个方法仅仅在类实现部分定义,根本不放在类接口部分定义,程序也依然可通过NSObject提供的performSelector:或performSelector:withObject:方法调用到Objective-C对象的方法。
key路径
在KVC协议中操作key路径的方法如下- setValue:forKeyPath::根据key路径设置属性值。 - valueForKeyPath::根据key路径获取属性值。
实际上,通过KVC操作对象的性能比通过setter、getter方法操作的性能更差,使用KVC的优势在于编程更加灵活,更适合提炼一些通用性质的代码。由于KVC方式允许通过字符串形式来操作对象的属性,这个字符串既可是常量,也可是变量,因此具有极高的灵活性。
键值监听(KVO)
KVO机制由NSKeyValueObserving协议提供支持,
NSObject遵守了该协议,所以
NSObject的子类(所有的
Objective-C类都是
NSObject的子类)都可以使用该协议中的方法,该协议包含了如下常用方法用于注册监听器
- addObserver:forKeyPath:options:context::注册一个监听器用于监听指定的key路径。 - removeObserver:forKeyPath::为key路径删除指定的监听器。 - removeObserver:forKeyPath:context::为key路径删除指定的监听器。
例: 在.h文件中定义 @property (nonatomic ,weak ) FKItem * item; - (void) showItemInfo; 在.m文件中定义 - (void) showItemInfo{ NSLog(@"item物品名为%@,物品价格为price:%d",self.item.name,self.item.price); } //自定义setItem:方法 - (void) setItem :(FKItem *)item{ self->_item = item; //为item添加监听器,监听item的name属性的改变 [self.item addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; //为item添加监听器,监听item的name属性的改变 [self.item addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew context:nil]; } //重写该方法,当被监听的数据模型组件发生改变时,就会调用监听器的该方法 - (void) observerValueForKeyPath:(NSString *)keyPath ofObject:(id) object change:(NSDictionary *)change context:(void *)context{ NSLog(@"--observerValueForKeyPath方法被调用--"); NSLog(@"被修改的keyPath为:%@",keyPath); NSLog(@"被修改的对象为:%@",object); NSLog(@"被修改的属性值为:%@",[change objectForKey:@"new"]); NSLog(@"被修改的上下文为:%@",context); } - (void) dealloc{ //删除监听器 [self.item removeObserver:self forKeyPath:@"name"]; [self.item removeObserver:self forKeyPath:@"price"]; }
相关文章推荐
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#中面向对象编程机制之多态学习笔记
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- C#面向对象特征的具体实现及作用详解
- C# 面向对象的基本原则
- 浅谈对c# 面向对象的理解
- Ruby面向对象编程详解
- php学习 面向对象 课件第1/2页
- PHP程序61条面向对象分析设计的经验小结
- 收集学习asp.net比较完整的面向对象开发流程
- javascript 面向对象编程 万物皆对象
- 不错的JavaScript面向对象的简单入门介绍第1/2页
- [推荐]javascript 面向对象技术基础教程
- javascript 面向对象的JavaScript类
- JavaScript中的面向对象介绍
- javascript实现面向对象类的功能书写技巧
- Javascript 面向对象 继承