KVC/KVO

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"];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值