kvo /kvc
来源:互联网 发布:广东进出口数据 编辑:程序博客网 时间:2024/05/21 09:30
}
- (void)viewDidLoa
{
[super viewDidLoad];
//[self kvcAppModel];
//[self kvcStudentModel];
//[self kvcDict];
[self kvo];
}
#pragma mark - KVO
- (void)kvo {
_person = [[Person alloc] init];
NSArray *arr = @[@"setter方法修改_age",@"kvc修改_age值",@"其他直接修改变量_age"];
for ( NSInteger i = 0; i < arr.count; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(10, 100+40*i, 300, 30);
[button setTitle:arr[i] forState:UIControlStateNormal];
[button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 101+i;
[self.view addSubview:button];
}
//给_person指向的对象 增加一个键值观察者
/**
监听 _person指向的对象 指定属性有没有 用kvc 或者 setter 修改
第一个参数就是观察者对象地址
2 监听的属性路径
3 监听新值和旧值 NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
4 NULL
*/
[_person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
}
#pragma mark - kvo监听到修改时那么观察者会调用
/**
* kvo监听到修改(kvc修改/setter修改)时那么观察者会调用
*
* @param keyPath 属性路径
* @param object 被监听的对象 _person指向的对象
* @param change 变化内容(new/old)
* @param context 增加观察时传入的
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"kvo监听到了");
if ([object isKindOfClass:[Person class]]) {
//判断被监听的对象
if ([keyPath isEqualToString:@"age"]) {
//判断被监听对象的指定属性
NSLog(@"_age被kvc/setter修改了");
NSLog(@"old_age:%@",change[@"old"]);
NSLog(@"old_age:%@",change[@"new"]);
//NSLog(@"dict:%@",change);
//或者
NSLog(@"old_age:%@",change[NSKeyValueChangeOldKey]);
NSLog(@"old_age:%@",change[NSKeyValueChangeNewKey]);
}
}
}
- (void)btnClick:(UIButton *)button {
switch (button.tag) {
case 101://setter
{
_person.age = 30;
}
break;
case 102://kvc赋值
{
[_person setValue:@(25) forKeyPath:@"age"];
}
break;
case 103://其他
{
[_person changeAge];
}
break;
default:
break;
}
}
//self.name = @"xiaohong"; _name = @"xiaohong";
#pragma mark - 常见kvc
- (void)kvcDict {
//把 一个对象的属性名 和 属性值 放入一个字典 利用kvc 赋值
NSDictionary *dict = @{@"price":@(1.23),@"name":@"内涵"};
AppModel *model = [[AppModel alloc] init];
//kvc 同时对 多个属性赋值
[model setValuesForKeysWithDictionary:dict];
NSLog(@"name:%@",[model valueForKeyPath:@"name"]);
[model release];
}
- (void)kvcStudentModel {
//kvc 对StudentModel的属性进行赋值
StudentModel *stu = [[StudentModel alloc] init];
[stu setValue:@"xiaohong" forKeyPath:@"name"];
AppModel *app = [[AppModel alloc] init];
#if 0
[app setValue:@(1.23) forKeyPath:@"price"];
[app setValue:@"内涵" forKeyPath:@"name"];
//kvc 对_appModel赋值
[stu setValue:app forKeyPath: @"appModel"];
#else
//使用 keyPath 属性路径赋值
[stu setValue:app forKeyPath:@"appModel"];
//对属性的属性赋值
[stu setValue:@(1.23) forKeyPath:@"appModel.price"];
[stu setValue:@"内涵" forKeyPath:@"appModel.name"];
#endif
NSLog(@"appName:%@",[app valueForKeyPath:@"name"]);
[app release];
NSLog(@"name:%@",[stu valueForKeyPath:@"name"]);//kvc 获取值
NSLog(@"app:%@",[stu valueForKeyPath:@"appModel"]);//kvc 获取值
[stu release];
}
-(void)kvcAppModel {
AppModel *model = [[AppModel alloc] init];
//1.使用kvc进行赋值 对model 的两个成员变量赋值
//key 属性
//value 就是属性的值
[model setValue:@(12.1) forKey:@"price"];
[model setValue:@"内涵段子" forKey:@"name"];
NSLog(@"%f",[model testFunc]);//12.1
NSLog(@"%@",[model testFunc2]);//内涵段子
//2.通过属性路径 keyPath 对属性赋值
[model setValue:@(121.0) forKeyPath:@"price"];
[model setValue:@"内涵" forKeyPath:@"name"];
/*
kvc 赋值的原理
运行时
会根据 提供的key/keyPath @"price" 会去当前model指向对象的类找 有没有- setPrice:方法(如果有那么就直接调用) 如果没有那么 就会去model执行的对象类中找没有成员变量(属性)price(如果有那么就直接对price赋值)如果没有那么继续找有没有_price 成员变量,如果有那么直接对_price赋值 ,如果没有那么直接崩溃
//如果要防止 崩溃 那么实现
- setValue:forUndefinedKey:
*/
NSLog(@"%f",[model testFunc]);//12.1
NSLog(@"%@",[model testFunc2]);//内涵段子
[model setValue:@"xiaohong" forKeyPath:@"xxx"];
//kvc 还可以 获取值
/*获取值原理
运行时
valueForKeyPath:
首先 会找 model 所属的类有没有 getter方法- (NSString*)name;
如果有那么直接调用,如果没有会找有没有成员变量name 如果有那么直接返回name的值,如果没有那么就找有没有成员变量_name,如果有那么直接返回_name的值 如果没有程序崩溃。除非实现下面的方法
- valueForUndefinedKey:
*/
NSString *name = [model valueForKeyPath:@"name"];
NSLog(@"name:%@",name);
[model valueForKeyPath:@"yyy"];
[model release];
}
- (void)viewDidLoa
{
[super viewDidLoad];
//[self kvcAppModel];
//[self kvcStudentModel];
//[self kvcDict];
[self kvo];
}
#pragma mark - KVO
- (void)kvo {
_person = [[Person alloc] init];
NSArray *arr = @[@"setter方法修改_age",@"kvc修改_age值",@"其他直接修改变量_age"];
for ( NSInteger i = 0; i < arr.count; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(10, 100+40*i, 300, 30);
[button setTitle:arr[i] forState:UIControlStateNormal];
[button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 101+i;
[self.view addSubview:button];
}
//给_person指向的对象 增加一个键值观察者
/**
监听 _person指向的对象 指定属性有没有 用kvc 或者 setter 修改
第一个参数就是观察者对象地址
2 监听的属性路径
3 监听新值和旧值 NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
4 NULL
*/
[_person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
}
#pragma mark - kvo监听到修改时那么观察者会调用
/**
* kvo监听到修改(kvc修改/setter修改)时那么观察者会调用
*
* @param keyPath 属性路径
* @param object 被监听的对象 _person指向的对象
* @param change 变化内容(new/old)
* @param context 增加观察时传入的
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"kvo监听到了");
if ([object isKindOfClass:[Person class]]) {
//判断被监听的对象
if ([keyPath isEqualToString:@"age"]) {
//判断被监听对象的指定属性
NSLog(@"_age被kvc/setter修改了");
NSLog(@"old_age:%@",change[@"old"]);
NSLog(@"old_age:%@",change[@"new"]);
//NSLog(@"dict:%@",change);
//或者
NSLog(@"old_age:%@",change[NSKeyValueChangeOldKey]);
NSLog(@"old_age:%@",change[NSKeyValueChangeNewKey]);
}
}
}
- (void)btnClick:(UIButton *)button {
switch (button.tag) {
case 101://setter
{
_person.age = 30;
}
break;
case 102://kvc赋值
{
[_person setValue:@(25) forKeyPath:@"age"];
}
break;
case 103://其他
{
[_person changeAge];
}
break;
default:
break;
}
}
//self.name = @"xiaohong"; _name = @"xiaohong";
#pragma mark - 常见kvc
- (void)kvcDict {
//把 一个对象的属性名 和 属性值 放入一个字典 利用kvc 赋值
NSDictionary *dict = @{@"price":@(1.23),@"name":@"内涵"};
AppModel *model = [[AppModel alloc] init];
//kvc 同时对 多个属性赋值
[model setValuesForKeysWithDictionary:dict];
NSLog(@"name:%@",[model valueForKeyPath:@"name"]);
[model release];
}
- (void)kvcStudentModel {
//kvc 对StudentModel的属性进行赋值
StudentModel *stu = [[StudentModel alloc] init];
[stu setValue:@"xiaohong" forKeyPath:@"name"];
AppModel *app = [[AppModel alloc] init];
#if 0
[app setValue:@(1.23) forKeyPath:@"price"];
[app setValue:@"内涵" forKeyPath:@"name"];
//kvc 对_appModel赋值
[stu setValue:app forKeyPath: @"appModel"];
#else
//使用 keyPath 属性路径赋值
[stu setValue:app forKeyPath:@"appModel"];
//对属性的属性赋值
[stu setValue:@(1.23) forKeyPath:@"appModel.price"];
[stu setValue:@"内涵" forKeyPath:@"appModel.name"];
#endif
NSLog(@"appName:%@",[app valueForKeyPath:@"name"]);
[app release];
NSLog(@"name:%@",[stu valueForKeyPath:@"name"]);//kvc 获取值
NSLog(@"app:%@",[stu valueForKeyPath:@"appModel"]);//kvc 获取值
[stu release];
}
-(void)kvcAppModel {
AppModel *model = [[AppModel alloc] init];
//1.使用kvc进行赋值 对model 的两个成员变量赋值
//key 属性
//value 就是属性的值
[model setValue:@(12.1) forKey:@"price"];
[model setValue:@"内涵段子" forKey:@"name"];
NSLog(@"%f",[model testFunc]);//12.1
NSLog(@"%@",[model testFunc2]);//内涵段子
//2.通过属性路径 keyPath 对属性赋值
[model setValue:@(121.0) forKeyPath:@"price"];
[model setValue:@"内涵" forKeyPath:@"name"];
/*
kvc 赋值的原理
运行时
会根据 提供的key/keyPath @"price" 会去当前model指向对象的类找 有没有- setPrice:方法(如果有那么就直接调用) 如果没有那么 就会去model执行的对象类中找没有成员变量(属性)price(如果有那么就直接对price赋值)如果没有那么继续找有没有_price 成员变量,如果有那么直接对_price赋值 ,如果没有那么直接崩溃
//如果要防止 崩溃 那么实现
- setValue:forUndefinedKey:
*/
NSLog(@"%f",[model testFunc]);//12.1
NSLog(@"%@",[model testFunc2]);//内涵段子
[model setValue:@"xiaohong" forKeyPath:@"xxx"];
//kvc 还可以 获取值
/*获取值原理
运行时
valueForKeyPath:
首先 会找 model 所属的类有没有 getter方法- (NSString*)name;
如果有那么直接调用,如果没有会找有没有成员变量name 如果有那么直接返回name的值,如果没有那么就找有没有成员变量_name,如果有那么直接返回_name的值 如果没有程序崩溃。除非实现下面的方法
- valueForUndefinedKey:
*/
NSString *name = [model valueForKeyPath:@"name"];
NSLog(@"name:%@",name);
[model valueForKeyPath:@"yyy"];
[model release];
}
0 0
- KVC、KVO
- KVO/KVC
- kvc 、kvo
- KVO/KVC
- KVC/KVO
- KVO/KVC
- KVC、KVO
- KVO/KVC
- KVO/KVC
- KVO/KVC
- KVC/KVO
- KVO/KVC
- KVO&KVC
- KVO & KVC
- KVC、KVO
- KVO/KVC
- kvo,kvc
- KVC、KVO
- 学习单片机的八个步骤总结
- poj 3278 Catch That Cow(bfs)
- Android_SDK各版本之间的差距
- MySQL索引和优化查询
- 重写代码,是否还要继续?
- kvo /kvc
- 第八周项目三-分数类中的运算符重载
- 今早起来ubuntu系统突然开不了机了,一直卡在logo界面
- JavaScript the Good Parts 读书笔记
- 脸秀-用颜值和世界刚正面
- 1022 - Can't write; duplicate key in table '#sql-1500_26'
- VLC字幕不显示以及乱码白框方框问题解决办法
- 矩阵卷积的快速算法
- openssl简介以及源码移植的交叉编译和安装