1. KVC 键值编码,他的作用是 可以通过字符串来访问属性
KVO 的优点:
当有属性改变,KVO 会提供自动的消息通知。这样开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知。
这是 KVO 机制提供的最大的优点。因为这个方案已经被明确定义,获得框架级支持,可以方便地采用。
开发人员不需要添加任何代码,不需要设计自己的观察者模型,直接可以在工程里使用。
其次,KVO 的架构非常的强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值。
Student类
#import <Foundation/Foundation.h>
#import "Teacher.h"
@interface Student :NSObject
@property(retain,nonatomic)NSString *name;
@property(assign,nonatomic)int age;
@property(retain,nonatomic)Teacher *teacher;
//重写
//对未定义的键的取值的处理
-(id)valueForUndefinedKey:(NSString *)key;
//对未定的键的设置的处理
-(void)setValue:(id)value forUndefinedKey:(NSString *)key;
.m
#import "Student.h"
@implementation Student
-(id)valueForUndefinedKey:(NSString *)key
{
NSLog(@"Student:该键不存在!取毛线值啊,亲");
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
NSLog(@"Student:不存在该属性啊,设置毛线啊,亲");
}
==============================================================
Teacher类
@interface Teacher :NSObject
@property(copy,nonatomic)NSString *tname;
@property(assign,nonatomic)int tage;
//对未定义的键的取值的处理
-(id)valueForUndefinedKey:(NSString *)key;
//对未定的键的设置的处理
-(void)setValue:(id)value forUndefinedKey:(NSString *)key;
#import "Teacher.h"
@implementation Teacher
@synthesize tage,tname;
-(id)valueForUndefinedKey:(NSString *)key
{
NSLog(@"Teacher:该键不存在!取毛线值啊,亲");
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
NSLog(@"Teacher:不存在该属性啊,设置毛线啊,亲");
}
-(void)dealloc
{
[tnamerelease];
[superdealloc];
}
@end
==============================================================
.main
注意区别 forKey 和 forKeyPath
Student *stu = [Studentnew];
[stusetValue:@"zhangsan"forKey:@"name"];
//不存在属性 name1 会调用-(id)valueForUndefinedKey:(NSString *)key;
[stu setValue:@"zhangsan"forKey:@"name1"];
[stu setValue:[NSNumbernumberWithInt:23]forKey:@"age"];
//不存在name1这个键 会调用重写的方法 -(void)setValue:(id)value forUndefinedKey:(NSString *)key;
NSString *a = [stu valueForKey:@"name1"];
NSLog(@"%@-%d",stu.name,stu.age);
Teacher *teach = [[Teacheralloc] init];
[stusetValue:teach forKey:@"teacher"];
[stu setValue:@"lisi"forKeyPath:@"teacher.tname"];
//同样可以在Teacher类里面对未定义的键的 设置和取值做处理如下不存在 tage1
[stu setValue:[NSNumbernumberWithInt:33]forKeyPath:@"teacher.tage1"];
NSLog(@"teacherd的值:%@-%d",teach.tname,teach.tage);
NSLog(@"stu获取值:%@-%d",[stuvalueForKeyPath:@"teacher.tname"],[[stuvalueForKeyPath:@"teacher.tage"] intValue
结果:
2013-08-20 13:32:32.808 demo[1732:303] Student:不存在该属性啊,设置毛线啊,亲
2013-08-20 13:32:32.832 demo[1732:303] Student:该键不存在!取毛线值啊,亲
2013-08-20 13:32:32.833 demo[1732:303] zhangsan-23
2013-08-20 13:32:32.833 demo[1732:303] Teacher:不存在该属性啊,设置毛线啊,亲
2013-08-20 13:32:32.834 demo[1732:303] teacherd的值:lisi-0
2013-08-20 13:32:32.834 demo[1732:303] stu获取值:lisi-0
2. KVO键值观察
创建一个对象(观察者)来观察另一个对象的键值变化
StudentObserver类
#import <Foundation/Foundation.h>
#import "Student.h"
@interface StudentObserver : NSObject
//观察者要关注的对象
@property(retain,nonatomic)Student *stu;
-(id)initWithStudent:(Student *)newStu;
@end
.m
#import "StudentObserver.h"
@implementation StudentObserver
-(id)initWithStudent:(Student *)newStu
{
if (self=[super init]) {
self.stu = newStu;
//为这个stu创建要观察的属性
//多个值 用 | 分开
[self.stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[self.stu addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//第一个参数常为:self 接受通知的对象 即为观察者
//第一个参数:键路劲参数 常为观察的键路劲
//第三个参数:标识KVO希望要如何传递给观察者 多个值 用 | 分开
//第四给参数一般都为nil
}
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"属性名:%@-从-%@-改为-%@",keyPath,[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);
}
-(void)dealloc
{
//除移观察者
[self.stu removeObserver:self forKeyPath:@"name"];
[self.stu removeObserver:self forKeyPath:@"age"];
[super dealloc];
}
Student *stu = [Student new];
//创建观察者来监听stu的变化
StudentObserver *observer=[[StudentObserver alloc] initWithStudent:stu];
[stu setValue:@"lisi" forKey:@"name"];
[stu setValue:@"zhangsan" forKey:@"name"];
[stu setValue:[NSNumber numberWithInt:12] forKey:@"age"];
[stu setValue:@"lisi" forKeyPath:@"teacher.tname"];
[stu release];
[observer release];
结果
2013-08-20 14:44:12.236 demo[2301:303] 属性名:name-从-<null>-改为-lisi
2013-08-20 14:44:12.254 demo[2301:303] 属性名:name-从-lisi-改为-zhangsan
2013-08-20 14:44:12.255 demo[2301:303] 属性名:age-从-0-改为-12