KVC和KVO

一、KVC:键值编码

1、创建三个类:Person、Car 和 JsonModel

Car类的实现部分如下:

#import "Car.h"
@interface Car()
@property (nonatomic, copy) NSString * carName;
@property (nonatomic, assign)int carPrice;
@end

@implementation Car

@end

Person类的实现部分如下:

#import "Person.h"
#import "Car.h"
@interface Person()
@property (nonatomic, copy) NSString * name;
@property (nonatomic, copy) NSString* pass;
@property (nonatomic, strong) NSDate * birth;
@property (nonatomic, copy,readonly) NSString * readName;
@property (nonatomic,assign) int price;
@property (nonatomic, strong) Car * car;//包含一个Car的实例对象
@end
@implementation Person


//对不存在的key赋值调用此方法
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"value = %@",value);
    NSLog(@"key = %@",key);
    if ([key isEqualToString:@"noExist"]) {
        NSLog(@"对不存在的key进行处理");
    }
}

//对不存在的key取值调用此方法
-(id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"key = %@",key);
    if ([key isEqualToString:@"noExist"]) {
        NSLog(@"对不存在的key进行处理");
    }
    return nil;
}
//处理value为nil时调用此方法(比如给int 类型赋值nil就会调用此方法)
-(void)setNilValueForKey:(NSString *)key{
    //对price进行处理
    if ([key isEqualToString:@"price"]) {
        key = 0;
    }
    else{
        [super setNilValueForKey:key];
    }
}

@end

JsonModel类的接口部分如下:

#import <Foundation/Foundation.h>

@interface JsonModel : NSObject
@property (nonatomic, strong) NSString * name;
@property (nonatomic, assign) int age;
@property (nonatomic, strong) NSArray * cars;
@end

ViewController类的实现部分:

#import "ViewController.h"
#import "Person.h"
#import "Car.h"
#import "JsonModel.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person * person = [[Person alloc] init];
    //person.name = @"大圣";//私有属性是无法赋值的
    //1、给私有属性赋值和取值
    [person setValue:@"大圣" forKey:@"name"];
    [person setValue:@"1455" forKey:@"pass"];
    [person setValue:[[NSDate alloc] init] forKey:@"birth"];
    NSLog(@"person.name = %@",[person valueForKey:@"name"]);
    NSLog(@"person.path = %@",[person valueForKey:@"pass"]);
    NSLog(@"person.birth = %@",[person valueForKey:@"birth"]);
    
    //person.readName = @"read";//只读属性是无法赋值的
    //2、给只读属性赋值和取值
    [person setValue:@"read" forKey:@"readName"];
    NSLog(@"readName = %@",[person valueForKey:@"readName"]);
    
    //3、给不存在的属性赋值和取值
    [person setValue:@"noExistValue" forKey:@"noExist"];
    NSLog(@"noExist = %@",[person valueForKey:@"noExist"]);
    
    //4、当value为nil时如何处理
    [person setValue:nil forKey:@"price"];
    NSLog(@"price = %@",[person valueForKey:@"price"]);
    
    //5、给可变字典赋值和取值
    NSMutableDictionary * dic = [[NSMutableDictionary alloc] init];
    [dic setValue:@"value1" forKey:@"key1"];// 类似于[dict setObject:@"value1" forKey:@"key1"];
    [dic setValue:@"value2" forKey:@"key2"];
    NSLog(@"key1的Value值为 = %@",[dic valueForKey:@"key1"]);// 类似于 [dict objectForKey:@"key1”];
    NSLog(@"key2的Value值为 = %@",[dic valueForKey:@"key2"]);
    
    //6、用字典给一个模型赋值,json解析时可用
    NSDictionary * jsonDict = @{
                                @"name":@"Jack",
                                @"age":@18,
                                @"cars":@[@"BMW",@"Benz"]
                                };
    JsonModel * jsonModel = [[JsonModel alloc] init];
    [jsonModel setValuesForKeysWithDictionary:jsonDict];
    NSLog(@"jsonModel.name = %@",jsonModel.name);
    NSLog(@"jsonModel.age = %d",jsonModel.age);
    NSLog(@"jsonModel.cars = %@",jsonModel.cars);
    
    //7-1、key路径给复合属性赋值和取值
    [person setValue:[[Car alloc] init] forKey:@"car"];//只有给car实例化后才能给car的属性赋值
    [person setValue:@"BMW" forKeyPath:@"car.carName"];//通过key路径给car.carName赋值
    NSLog(@"car.name = %@",[person valueForKeyPath:@"car.carName"]);//通过key路径对car.carName取值。
    
    //7-2、key路径与字典
    NSArray *arr = @[
                     @{
                         @"city":@"beijing",
                         @"person":@{
                                        @"name":@"zhangsan",
                                        @"city":@"guangzhou"
                                    }
                      },
                     
                     @{
                         @"city":@"chengdu"
                      }
                     
                     ];
    NSArray * arrCitys = [arr valueForKeyPath:@"city"] ;
    //可以获取到arrCitys数组 @[@"beijing",@"guangzhou",@"chengdu"]
    NSLog(@"arrCitys = %@",arrCitys);
    
    //7-3、key路径与数组
    NSArray * array = @[@1,@2,@3,@4,@5];
    CGFloat sum = [[array valueForKeyPath:@"@sum.floatValue"] floatValue];//求和
    CGFloat avg = [[array valueForKeyPath:@"@avg.floatValue"] floatValue];//平均值
    CGFloat max =[[array valueForKeyPath:@"@max.floatValue"] floatValue];//最大值
    CGFloat min =[[array valueForKeyPath:@"@min.floatValue"] floatValue];//最小值
    NSLog(@"sum = %f,avg = %f,max = %f,min = %f",sum,avg,max,min);
    
    
    /*
    PS:
     以Person类的name属性为例
     1、程序优先考虑调用setName:方法来进行赋值
     2、如果没有setName:方法会搜索名称为_name成员变量,不论该成员变量是在接口部分还是实现部分也不论用什么控制符修饰
     3、如果_name不存在,就会搜索名称为name的成员变量,不论该成员变量是在接口部分还是实现部分也不论用什么控制符修饰
     4、如果上述三条都不满足就会调用setValue:forUndefineKey:方法,要想对不存在的属性进行处理在Person类内的实现部分重写此方法
     */
    
    /*
     PS:
     以name属性为例
     1、程序优先考虑调用name:方法来进行赋值
     2、如果没有name:方法会搜索名称为_name成员变量,不论该成员变量是在接口部分还是实现部分也不论用什么控制符修饰
     3、如果_name不存在,就会搜索名称为name的成员变量,不论该成员变量是在接口部分还是实现部分也不论用什么控制符修饰
     4、如果上述三条都不满足就会调用valueforUndefineKey:方法,要想对不存在的属性进行处理在Person类内的实现部分重写此方法
     */
}


二、KVO:键值监听

将Person类的car属性移到接口文件,

在Car类的接口文件增加NSString * color;和NSString * speed;两个属性

在Person类的实现文件内增加如下方法

//设置person.car的时候就给car添加键值观察者
-(void)setCar:(Car *)car{
    _car = car;
    //新值旧值一起观察,即可以将新的value和就的value都传到change数组,这样在调用方法中就可以拿到这两个值
    [_car addObserver:self forKeyPath:@"color" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    [_car addObserver:self forKeyPath:@"speed" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}
//只要person.car.color属性或者person.car.speed属性发生改变就会调用这个方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    NSLog(@"调用了观察者方法");
    NSLog(@"keyPath = %@",keyPath);
    NSLog(@"object = %@",object);
    NSLog(@"change = %@",change);
    NSLog(@"new = %@",change[@"new"]);
    NSLog(@"old = %@",[change objectForKey:@"old"]);
    NSLog(@"context = %@",context);
}

- (void)dealloc
{
    //移除监听者
    [self.car removeObserver:self forKeyPath:@"color"];
    [self.car removeObserver:self forKeyPath:@"speed"];
}

在ViewController.m文件内增加如下方法

//创建person实例及person.car实例并赋值
-(void)kvoTest{
    [self createButton];
    Car * car = [[Car alloc] init];
    self.car = car;
    car.color = @"white";
    Person * person = [[Person alloc] init];
    person.car = car;//此行代码会为person对象的car属性添加观察者
    self.person = person;
}
//创建button
-(void)createButton{
    UIButton * myBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    myBtn.frame = CGRectMake(40, 80, 100, 50);
    [myBtn setTitle:@"按钮" forState:UIControlStateNormal];
    myBtn.backgroundColor = [UIColor blueColor];
    [myBtn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:myBtn];
}
//button的点击事件
-(void)clickBtn:(UIButton*)btn{
    //只要person.car的属性发生改变就会调用观察者方法
    self.person.car.color = @"black";
    self.person.car.speed = 200;
    
}


参考文献:

1、KVC/KVO原理详解及编程指南 - 王中周的个人博客 - 博客频道 - CSDN.NET

2、你不知道的valueForKeyPath - 简书



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值