1. KVC
KVC一种间接更改对象状态的方式,其实现方法是使用字符串来描述对象需要更改的属性。
KVC中的基本调用包括valueForKey:和setValue:ForKey:,以字符串的形式向对象发送消息.
声明两个对象用于测试如下:
@interface Student : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) int score;
@property (nonatomic,strong) Book *book;
@property (nonatomic,strong) NSArray *stus;
@end
@interface Book : NSObject
@property (nonatomic,copy) NSString *bookname;
@end
以上就是Student Book 两个头文件,由于暂时不需要.m文件里干任何事,所以这就不贴.m代码了
测试代码:
void testKvc(){
/1.kvc 简单用法///
Student *student = [[Student alloc]init];
//kvc 设置值
[student setValue:@"lk" forKey:@"name"];
[student setValue:@"90" forKey:@"score"];
Book *book = [[Book alloc]init];
book.bookname = @"book-one";
[student setValue:book forKey:@"book"];
//kvc 取值
NSLog(@"name:%@",[student valueForKey:@"name"]);
//name:lk
NSLog(@"score:%@",[student valueForKey:@"score"]);
//score:90
NSLog(@"bookname:%@",[student valueForKeyPath:@"book.bookname"]);
//bookname:book-one
/2. kvc 批量设置值///
Student *stu = [[Student alloc]init];
NSArray *keys = [NSArray arrayWithObjects:@"name",@"score", nil];
NSArray *values = [NSArray arrayWithObjects:@"student-lk",[NSNumber numberWithInt:100], nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
//批量设置值
[stu setValuesForKeysWithDictionary:dict];
NSLog(@"name:%@",[stu valueForKey:@"name"]);
//name:student-lk
NSLog(@"score:%@",[stu valueForKey:@"score"]);
//score:100
//批量获取值
NSLog(@"values:%@",[stu dictionaryWithValuesForKeys:keys]);
//values:{
// name = "student-lk";
// score = 100;
//}
/3.对数组的操作///
Student *s1 = [[Student alloc]init];
s1.name = @"student-01";
s1.score = 90;
Student *s2 = [[Student alloc]init];
s2.name = @"student-02";
s2.score = 85;
Student *s3 = [[Student alloc]init];
s3.name = @"student-03";
s3.score = 76;
[s3 setValue:@[s1,s2,s3] forKey:@"stus"];
NSLog(@"s3 count:%lu",s3.stus.count);
//s3 count:3
NSLog(@"s3 count-2:%@",[s3 valueForKeyPath:@"stus.@count"]);
//s3 count-2:3
NSLog(@"max score:%@",[s3 valueForKeyPath:@"stus.@max.score"]);
//max score:90
NSLog(@"avg score:%@",[s3 valueForKeyPath:@"stus.@avg.score"]);
//avg score:83.666666666666666666666666666666666666
}
KVC赋值查找方式,
[student setValue:@"lk"forKey:@"name"];
以这为例子,
KVC 在setValue:ForKey时会先查找其setter方法, 如果不存在setter方法,就在类中查找名为name或者_name的实例变量,然后为它赋值。
2. KVO
KVO是一种非常重要的机制, 主要用于监听对象的属性的变化.
在刚刚的Student.h文件添加一个监听对象
@interface Student : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) int score;
@property (nonatomic,strong) Book *book;
@property (nonatomic,strong) NSArray *stus;
@end
#pragma kvo
@interface StudentObserver : NSObject
@end
.m文件如下:
@implementation Student
@end
@implementation StudentObserver
/**
* keyPath 被监听的key 值
* object 被监听的对象
* change存放着新旧值,取决于外面监听方法options 的设置
* context 外面存放过来的值
*
**/
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"%@",keyPath);
//name
NSLog(@"%@",object);
// <Student: 0x1002033d0>
NSLog(@"%@",change);
//{
// kind = 1;
//new = "student-change";
//old = "student-01";
//}
NSLog(@"%@",context);
//params
}
测试方法(执行结果在.m中已经写出来了,这里主要看下测试的代码):
void testKvo(){
Student *student = [[Student alloc]init];
student.name = @"student-01";
student.score = 98;
//监听
StudentObserver *stuObserver = [[StudentObserver alloc]init];
//observer 哪个对象用于其监听
//keyPath 被监听的的key值
//options 枚举类型,根据其设置监听对象方法字典里存放啥值
//context 该参数设置的值会传到监听StudentObserver 监听方法里
[student addObserver:stuObserver forKeyPath:@"name" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:@"params"];
//改变name值,查看控制台输出
student.name = @"student-change";
//移除
[student removeObserver:stuObserver forKeyPath:@"name"];
}