关于 KVO 和 KVC 的一些总结 以及使用KVC进行字典和模型的互相转换

来源:互联网 发布:unity3d angrybots 编辑:程序博客网 时间:2024/06/06 08:35

一直对KVO 和KVC都是停留在 只是知道的情况,从来没有尝试这在项目中使用,最近准备总结一下,在项目里面简单的使用一下

1、什么是KVO?

KVO其实就是Key-Value-Observer,也就是键值观察者,是基于KVC机制实现的另一种模式。也许有不少同学用过SVPullToRefresh或者MJRefresh刷新组件,都使用了KVO来实现。

看了一下感觉kvo有些地方和通知有一些相同的地方,因此在有时候可以使用KVO来代替通知,


举个栗子,

在当前VC里面,当另外一个dataModel类中的某个属性变化时,我需要即时的得到dataModel变化的信息,并且得到所变化的值,这个时候使用键值观察者模式就非常方便了

下面为dataModel类:

#import <Foundation/Foundation.h>#import "KVOClass.h"@interface Student : NSObject@property(nonatomic) NSString *studentName;@property (nonatomic) float grade;@property(nonatomic)KVOClass *kvoClass;@end

设置一秒之后改变  数据模型中的 属性  studentName的值,

-(void)changename{    self.studentName =@"学生的名字改为+++老王了";        [selfsetValue:@"学生的名字改为+++老王了"forKey:@"studentName"];}


VC里面,dataModel类的对象添加一个观察者来检测

这样只要model类属性发生变化,这边既可以得到通知,实现对应的逻辑功能即可,一般做数据的更新比较方便。。。

#import "KVOClass.h"#import "Student.h"#import "Teacher.h"@implementation KVOClass- (instancetype)init{    self = [super init];    if (self) {         self.student= [[Student alloc]init];        self.teacher = [[Teacher alloc]init];                //某一对象本身添加 本类对象 为观察者        [self addObserver:self   forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"name"];        //某一对象添加本类对象为观察者        [self.student  addObserver:self    forKeyPath:@"studentName"  options:0|1context:nil];                //某一对象添加其他类对象为观察者        [self.student   addObserver:self.teacher    forKeyPath:@"studentName"  options:0|1context:nil];            }    return  self;}


实现收到通知的方法;哪个类 添加观察者 ,哪个类就负责实现这个方法

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{    if (context == @"name") {        NSLog(@"%@",self.name);    }else if ([keyPath isEqualToString:@"studentName"]){//回调方法必须处理,否则会crash掉!!!!!!!         NSLog(@"本类对象++++%@",self.student.studentName);    }else {        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];    }}


下面是在其他类Teacher中处理回调函数的情况

/****

 change  通知回调的参数,包含所检测对象的值的变化  change[@"new"]即可取到

 注意!!!  change[@"new"]取到的值全是对象数据类型,没有基本数据类型的(如果是 int float等,得到的是NSNumber类型)

 同样的  kvc的时候赋值的时候也要是对象类型,基本类型数据要转成对象类型的

 *****/



-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{    if ([keyPath isEqualToString:@"studentName"]) {        NSLog(@"老师貌似收到了学生信息改变的通知了,+++%@",change[@"new"]);    }else if ([keyPath isEqualToString:@"grade"]){      NSLog(@"老师貌似收到了学生信息改变的通知了,+++%@",change[@"new"]);    }}


移除观察者, 哪个类 添加观察者 ,哪个类就负责移除观察者

-(void) dealloc{    [self removeObserver:self forKeyPath:@"name"];    [self.student removeObserver:self forKeyPath:@"studentName"];    [self.student removeObserver:self.teacher forKeyPath:@"studentName"];    [self.student removeObserver:self.teacher forKeyPath:@"grade"];}


总结一下:

//总结   1、谁成为观察者,谁就要实现收到通知的回调方法,可以在当前类(添加观察者的类),也可以在观察者的类中去实现,

//      2、添加观察者与移除观察者是成对出现的,一定要记得移除,原则是在那个类添加就在那个类移除观察者。否则会crash!!!

//      3、某一对象可以添加当前类的对象为观察者,也可以添加其他类的对象为观察者,

                                                                                                    。                                                                              KVC和字典转模型

http://www.2cto.com/kf/201507/415647.html

http://www.bkjia.com/IOSjc/989396.html

 //******************  使用 KVC 自动字典转模型 ******************//    NSDictionary *dic = @{@"name":@"cheng",@"nick":@"laocheng",@"addr":@"henan",@"phone":@(10086),@"test":@"false"};    Student *student = [[Student alloc]init];    [student setValuesForKeysWithDictionary:dic];   // 使用 KVC 自动字典转模型,实体类只有声明一下属性,此方法可以自动把字典的key                                                    //和value 分别赋给 实体//    /如果kvc转模型的时候 传的字典里面的key如果没有对应属性的key时,会自动调用此方法//    -(void)setValue:(id)value forUndefinedKey:(NSString *)key{    NSLog(@"phone : %@",student.phone);         //******************  使用 KVC 自动模型转字典 ******************//    NSDictionary *dict = [student dictionaryWithValuesForKeys:@[@"name",@"nick",@"addr",@"phone"]];    NSLog(@"dict : %@",dict);

数据模型

@interface Student : NSObject@property(nonatomic)NSString *name;@property(nonatomic)NSString *nick;@property(nonatomic)NSString *addr;@property(nonatomic)NSNumber *phone;@property(nonatomic)NSString *testProperty;@end


                                             
0 0