在编码过程中,我们经常要搬到目标是否发生改变,以便于及时的做出对应的处理。这时候如果我们通过回调的方式来实现就破坏了程序的完整性,如果我们做一个定时器,定时检查,实时性不高不说,还影响程序性能。oc运行时提供了这个问题的解决方案,就是KVO。
键值观察(KVO)是基于键值编码(KVC)的一种技术;利用键值观察可以注册成为一个对象的观察者,在该对象的某个属性变化时收到通知。
键值观察分为以下三步:
注册成为观察者;
观察者定义KVO的回调
移除观察者
KVO实例
创建学生类作为被观察的对象
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property(nonatomic,retain)NSString *name;
@property(nonatomic,assign)int age;
@end
#import "Student.h"
@implementation Student
-(NSString *)description{
NSString *str = [NSString stringWithFormat:@"name:%@,age:%d",self.name,self.age];
return str;
}
-(void)dealloc{
[_name release];
[super dealloc];
}
@end
创建观察者 有一个学生类型的属性,并将自己注册成为学生类的观察者 重写了观察类的回调方法以便在被观察者的属性改变时接收到通知,最后移除观察者
#import <Foundation/Foundation.h>
#import "Student.h"
@interface StudentObserver : NSObject
@property(nonatomic,retain)Student *stu;
-(id)initWithStudent:(Student *)theStu;
@end
#import "StudentObserver.h"
@implementation StudentObserver
-(id)initWithStudent:(Student *)theStu{
self = [super init];
if(self){
self.stu = theStu;
[self.stu addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
[self.stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([keyPath isEqualToString:@"name"]){
NSString *oldName = [change objectForKey:NSKeyValueChangeOldKey];
NSString *newName = [change objectForKey:NSKeyValueChangeNewKey];
NSLog(@"键路径%@对应的值发生改变,从%@变成%@",keyPath,oldName,newName);
}else if ([keyPath isEqualToString:@"age"]){
NSNumber *oldAge = [change objectForKey:NSKeyValueChangeOldKey];
NSNumber *newAge = [change objectForKey:NSKeyValueChangeNewKey];
NSLog(@"键路径%@对应的值发生改变,从%@变成%@",keyPath,oldAge,newAge);
}
}
-(void)dealloc{
[self.stu removeObserver:self forKeyPath:@"name"];
[self.stu removeObserver:self forKeyPath:@"age"];
[super dealloc];
}
@end
main函数代码如下
#import <Foundation/Foundation.h>
#import "Student.h"
#import "StudentObserver.h"
int main(int argc, const char * argv[])
{
Student *stu = [[Student alloc] init];
StudentObserver *stuObserver = [[StudentObserver alloc] initWithStudent:stu];
[stu setValue:@"zhang san" forKey:@"name"];
[stu setValue:[NSNumber numberWithInt:18] forKey:@"age"];
[stu setValue:@"li si" forKey:@"name"];
[stu setValue:[NSNumber numberWithInt:22] forKey:@"age"];
[stu release];
[stuObserver release];
return 0;
}