您的位置:首页 > 移动开发 > IOS开发

iOS之KVC和KVO

2016-02-27 22:11 435 查看
/*
KVC是键值编码
提供一种间接访问对象属性的机制,而不是通过getter和setter
1.为指定属性设置值:setValue:属性值 forKey:属性名称
2.获取指定属性值:  valueForKey:属性名称

KVO是键值监听
只有通过KVC改变对象的属性值,才能被监听到
1.为某对象的某属性设置监听:addObserver:forKeyPath:options:context:
2.为key路径删除指定监听:  removeObserver:forKeyPath:context:
*/
#import "ViewController.h"
#import "JYPerson.h"

@interface ViewController ()
@property(nonatomic,strong)JYPerson *person;
@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];

JYPerson *person=[[JYPerson alloc]init];

[person setValue:@"顾金跃" forKey:@"name"];
//    [person setName:@"顾金跃123"];
//    person.name=@"顾金跃321";

[person setValue:@"173.5" forKey:@"height"];
[person setValue:@"135" forKey:@"weight"];

NSLog(@"姓名:%@  身高:%@  体重:%@",person.name,person.height,person.weight);
NSLog(@"姓名:%@  身高:%@  体重:%@",[person valueForKey:@"name"],[person valueForKey:@"height"],[person valueForKey:@"weight"]);

[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
[person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];
[person addObserver:self forKeyPath:@"weight" options:NSKeyValueObservingOptionNew context:nil];

self.person=person;

[self addButton];

}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"被修改的keyPath为:%@ 被修改的对象为:%@ 新被修改的属性值为:%@ 被修改的上下文为:%@",keyPath,[object class],[change objectForKey:@"new"],context);

NSLog(@"%@",self.person.name);
}
-(void)dealloc
{
[self.person removeObserver:self  forKeyPath:@"name"];
[self.person removeObserver:self forKeyPath:@"height"];
[self.person removeObserver:self forKeyPath:@"weight"];
}

-(void)addButton
{
UIButton *button=[UIButton buttonWithType:UIButtonTypeContactAdd];
button.frame=CGRectMake(100, 100, 50, 50);
[button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];

[self.view addSubview:button];
}

-(void)buttonClick
{
NSLog(@"点击");
self.person.name=@"123";
}
@end
<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">当某个类的对象第一次被观察时,</span><span style="font-family: Arial; font-size: 14px; line-height: 26px; color: rgb(255, 0, 0);">系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。派生类在被重写的 setter 方法实现真正的通知机制</span><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">,就如前面手动实现键值观察那样。这么做是基于设置属性会调用 setter 方法,而通过重写就获得了 KVO 需要的通知机制。当然前提是要通过遵循 KVO 的属性设置方式来变更属性值,如果仅是直接修改属性对应的成员变量,是无法实现 KVO 的。</span><br style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;" /><span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的 setter,从而激活键值通知机制。此外,派生类还重写了 dealloc 方法来释放资源。</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: