什么是KVC 什么是 KVO ?
KVC:(NSKey ValueCoding)”键-值 编码“是一种间接的访问对象属性(字符串表征)的机制。对象的属性都可以通过使用KVC机制用相同的方式访问。我们可以取而代之“设置器方法、点语法方法”去访问对象的属性。
KVO:(NSKey ValueObserving)"键-值 监听"是一种这样的机制,当对象的属性发生变化的时候,我们的监听者能够得到一个通知。
NSObject 类为所有的对象提供了一个自动检测能力的NSKey ValueObserving 协议。我们可以根据需要来打开这个监听机制。KVO是基于KVC而实现的。
KVC & KVO的使用
在使用KVC的时候,我们要注意,key 必须以小写字母开头,通常常和系统访问器方法同名。
获取属性:valueForKey:
设置属性:setValue: forKey:
KVC 对未定义的属性定义了 valueForUndefinedKey: 方法(重载方法获取定制的实现)
注意:KVC中的 value 都必须是对象。
基于KVC能够对对象的属性进行访问,当这个属性发生变化的时候,我们也能监听,这个监听的方法系统已经为我们实现了。我们所做的只需要去注册这个监听。注册之后就能很好的监听,属性的值变化了。下面就是KVO机制的注册和监听方法
1注册
-(void)addObserVer:(NSObject*)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
方法参数说明:keyPath 就是要观察的属性值,options 就是观察键值变化的选择 ,context 就是我们要传输的数据。其中options 是监听返回的字典所包含什么值。有两个常用的选项:NSKeyValueObservingOptionNew 返回的字典包含新值 NSKeyValueObservingOptionOld 指返回的字典包含旧值。
2.监听
-(void)obserValueForKeyPath:(NSString *)KeyPath ofObject(id)object change:(NSDictionary *)change context:(void *)context
其中 change 里存储了一些变化的数据,比如变化前的数据,变化后的数据。
实例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
———————————————————————————————————————————————(.m文件) #import "AppDelegate.h" #import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; ViewController * vc = [[ViewController alloc]init]; self.window.rootViewController = vc; return YES; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
———————————————————————————————————————————————(.h文件) #import <Foundation/Foundation.h> @interface Pweson : NSObject @property(nonatomic,copy)NSString * name; @property(nonatomic)NSInteger age; -(id)initWithDictionary:(NSDictionary *)dic; @end ———————————————————————————————————————————————(.m文件) #import "Pweson.h" @implementation Pweson -(id)initWithDictionary:(NSDictionary *)dic{ self = [super init]; if (self) { [self setValuesForKeysWithDictionary:dic]; } return self; } -(void)setValue:(id)value forUndefinedKey:(NSString *)key{ } @end
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
———————————————————————————————————————————————(.h文件) #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end ———————————————————————————————————————————————(.m文件) #import "ViewController.h" #import "Pweson.h" @interface ViewController () @property(nonatomic,copy)Pweson * person; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor lightGrayColor]; NSDictionary * dic = @{@"name":@"张华",@"age":@45}; _person = [[Pweson alloc] initWithDictionary:dic]; [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(80, 100, 180, 30)]; label.textAlignment = NSTextAlignmentCenter; label.text = _person.name; [self.view addSubview:label]; [label release]; UILabel * agelabel = [[UILabel alloc] initWithFrame:CGRectMake(280, 100, 60, 30)]; agelabel.tag = 101; agelabel.backgroundColor = [UIColor redColor]; agelabel.textAlignment = NSTextAlignmentCenter; agelabel.text = [NSString stringWithFormat:@"%ld",self.person.age]; [self.view addSubview:agelabel]; [agelabel release]; UIButton * but = [UIButton buttonWithType:UIButtonTypeSystem]; but.frame = CGRectMake(100, 350, 80, 50); but.tintColor = [UIColor blueColor]; [but setTitle:@"增加1岁" forState:UIControlStateNormal]; [but addTarget:self action:@selector(addAge:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:but]; [but release]; } -(void)addAge:(UIButton *)sender{ self.person.age += 1; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"age"]) { ((UILabel *)[self.view viewWithTag:101]).text = [NSString stringWithFormat:@"%ld",self.person.age]; } }