KVC/KVO

来源:互联网 发布:java运维工程师面试题 编辑:程序博客网 时间:2024/05/22 06:57

KVC传值/获取值

kvc用于多层对象之间的赋值传值。
1.key
示例:
KVCViewController 逻辑处理对象

 @property (nonatomic) Student *student;

Student 对象
Student.h文件

{    NSString *_zhuangBei;}@property (nonatomic,copy) NSString *name;@property (nonatomic) NSString *id;

Student.m文件
//私有变量

{    NSString *_daTui;}Computer对象:Computer.h文件
{    float _weight;}@property (nonatomic,copy) NSString *name;@property (nonatomic) float price;@property (nonatomic,copy) NSString *producePlace;

代码:

    //self.student->_zhuangBei    [self.student setValue:@"手机" forKey:@"zhuangBei"];    //_zhuangBei也可以    NSLog(@"%@",[self.student valueForKey:@"zhuangBei"]);    //私有的照样可以赋值和获取    [self.student setValue:@"长腿" forKey:@"daTui"];    NSLog(@"%@",[self.student valueForKey:@"daTui"]);

2.keypath
示例代码如下:

[self.student setValue:@3 forKeyPath:@"computer.weight"];    NSLog(@"***%@",[self.student valueForKeyPath:@"computer.weight"]);    [self setValue:@100 forKeyPath:@"student.computer.weight"];    NSLog(@"***%@",[self valueForKeyPath:@"student.computer.weight"]);

KVO属性观察者

注册观察者,是为了在观察值改变的时候及时进行相关处理。

// KVO Key-Value Observser
// 观察者模式,是一种设计模式
// 我们让当前控制器对象观察学生对象student的blood的变化
// 当学生对象blood一旦发生变化,当前控制器对象知道这么一个变化并做相应处理

// 观察者:当前视图控制器对象
// 被观察者:_student
如果没有注册观察者,而移除观察者,会crash

kvo 实现需要三步:
1.第一步 是注册观察
2.第二步 是实现观察方法
3.第三步 移除注册

//1. 注册观察者,让self(当前视图控制器对象)临听student

```- (void)regist {    // self.student: 被观察者    // 第一个参数:观察者,谁是观察者,这里写成了self, 即当前对象    // 第二个参数:观察student什么    // 第三个参数:选项,当student指定的keyPath发生变化时会把哪些值组装起来,以待回调给方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context    // 第四个参数:附加信息    [self.student addObserver:self forKeyPath:@"blood" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];    // self观察student的computer的price    [self.student addObserver:self forKeyPath:@"computer.price" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];}

//改变student属性值,触发监听

- (void)buttonClick:(id)sender {    int value = arc4random()%100;    // self.student.blood = value; // 通过点语法,实际上是通过set方法,可以触发kvo    // [self.student setValue:@(value) forKey:@"blood"]; // @(value)->[NSNumber numberWithInt:value] 通过kvc的方式也能触发kvo    // 如果是对student的成员直接赋值,不通点set方法和kvc赋值方式给blood赋值,不会触发kvo    // [self.student updateBlood:value]; // 在这个方法内部,直接:_blood = 100 这样不会触发kvo    // NSLog(@"%f", self.student.blood);    self.student.computer.price = value;}

2.实现观察方法
代码如下:

// 当student的blood发生变化时,当前对象就会检测到,调方法:// 第一个参数:观察的student的哪个属性的变化(可以是更深层的)// 第二个参数:观察的哪个对象 -- student// 第三个参数:观察到的值的变化,这些变化会放在字典change里面,我们可以通过它取到比如变化前的值和变化后的值// 第四个参数:NULL 附加信息- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {    if ([object isKindOfClass:[Student class]]) {        NSLog(@"是的,监听到学生对象发生了变化");    }    NSLog(@"keyPath: %@", keyPath);    if ([keyPath isEqualToString:@"blood"]) {        NSLog(@"学生对象的blood发生了变化");    }    NSNumber *newValue = change[NSKeyValueChangeNewKey];    NSNumber *oldVlaue = change[NSKeyValueChangeOldKey];    NSLog(@"变化前: %f  变化后:%f", [oldVlaue floatValue], [newValue floatValue]);}

3.移除观察者

// 学生对象被销毁了,但是仍然在监听(观察者没有移除注册,没有移除观察)- (void)dealloc {    // 当学生消失的时候,观察者对象没理由,也不能再去观察学生对象,所以移除观察    [_student removeObserver:self forKeyPath:@"blood"];    [_student removeObserver:self forKeyPath:@"computer.price"];}

对数组进行kvo 注册观察者

[self addObserver:self forKeyPath:@"data" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];    //这种添加方式不会观察//    [self.data addObject:@"data1"];    //通过这种方式添加才会被观察    [[self mutableArrayValueForKeyPath:@"data"] addObject:@"data2"];
0 0