iOS 利用KVC进行数据转模型

作者: calary | 来源:发表于2017-12-15 11:48 被阅读429次

    前言

    最近公司要求做一个SDK供三方使用,在制作过程中就碰到一个问题,因为要进行网络请求获取数据,并且为了避免冲突要尽量不使用三方框架,所以平时常用的数据转模型框架MJExtension就没有使用,而是用系统的KVC进行简单处理,为什么数据要转模型,这个就不多陈述了,好处不言而喻。

    KVC

    KVC的介绍可以参考iOS开发技巧系列---详解KVC(我告诉你KVC的一切)文章讲的很详细,下面我们进入我们的主题

    普通model

    我们先来看一个普通DogModel类

    //DogModel.h
    #import <Foundation/Foundation.h>
    
    @interface DogModel : NSObject
    @property (nonatomic, copy) NSString *pid;//id
    @property (nonatomic, copy) NSString *name;//名子
    @property (nonatomic, assign) int age;//年龄
    //初始化方法
    - (instancetype)initWithDictionary:(NSDictionary *)dic;
    @end
    
    //DogModel.m
    #import "DogModel.h"
    
    @implementation DogModel
    - (instancetype)initWithDictionary:(NSDictionary *)dic{
        if (self = [super init]){
            [self setValuesForKeysWithDictionary:dic];
        }
        return self;
    }
    
    - (void)setValue:(id)value forKey:(NSString *)key{
        //在这里更改key
        if([key isEqualToString:@"id"]){
            key = @"pid";
        }
        [super setValue:value forKey:key];
    }
    //冗错处理,如果有未定义的字段的话就会走到这里,不重写的话会引起崩溃
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key{
        NSLog(@"value:%@,undefineKey:%@",value,key);
    }
    @end
    
    • 我们在进行数据转模型时最重要的一个方法就是 setValuesForKeysWithDictionary
      他会遍历字典中的每一个key,然后进行赋值,
    • 你可以在- (void)setValue:(id)value forKey:(NSString *)key这个方法中监听到每一个key,有时候后台命名不符合我们或者是一个关键字,那么这时候就要把这个key值进行转换,例如:这里将id->pid;
    • 方法- (void)setValue:(id)value forUndefinedKey:(NSString *)key 如果key在model中没有定义,则会走到这里,要不然会崩溃,所以这个方法必须重写。
    • 实现效果,未定义的key打印了出来,model也赋值成功


      普通model测试

    带有NSArray的model

    先看下我们的PersonModel类

    //PersonModel.h
    #import <Foundation/Foundation.h>
    #import "DogModel.h"
    
    @interface PersonModel : NSObject
    @property (nonatomic, copy) NSString *name;
    //是否是小孩(<14岁)
    @property (nonatomic, assign) BOOL isChild;
    //性别(0-男 1-女)
    @property (nonatomic, assign) int sex;
    //男/女(根据sex进行处理后的结果)
    @property (nonatomic, copy) NSString *sexStr;
    //拥有的Dog(数组)
    @property (nonatomic, strong) NSArray <DogModel *> *dogs;
    
    //初始化方法
    - (instancetype)initWithDictionary:(NSDictionary *)dic;
    @end
    
    
    //PersonModel.m
    #import "PersonModel.h"
    @implementation PersonModel
    - (instancetype)initWithDictionary:(NSDictionary *)dic{
        if (self = [super init]){
            [self setValuesForKeysWithDictionary:dic];
        }
        return self;
    }
    
    - (void)setValue:(id)value forKey:(NSString *)key{
        //在这里处理数组转换
        if([key isEqualToString:@"dogs"]){
            NSMutableArray *array = [NSMutableArray array];
            for (NSDictionary *dic in value){
                DogModel *model = [[DogModel alloc] initWithDictionary:dic];
                [array addObject:model];
            }
            //注意这个地方不能用变量名dogs,一定要用value,不然转换后的模型则没有赋值进去
            value = array;
        }
        [super setValue:value forKey:key];
    }
    //冗错处理,如果有未定义的字段的话就会走到这里,不重写的话会引起崩溃
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key{
        NSLog(@"value:%@,undefineKey:%@",value,key);
    }
    
    //重写sexStr的get方法
    - (NSString *)sexStr{
        if (self.sex == 0){
            return @"男";
        }else {
            return @"女";
        }
    }
    @end
    
    • 数组的处理主要在方法- (void)setValue:(id)value forKey:(NSString *)key中,就是将拿到的数组进行遍历,然后赋值到DogModel存入新数组返回;
    • 对于Bool类型的处理,在获得数据是0是自动为NO,非0即为YES;
    • 对于后台给的type根据数值判断的我们可以在Model里进行处理,这里sex 0-男 1-女,自己定义了一个属性sexStr,根据需要对sex进行了转化,如果在哪里需要显示男女的话可以直接通过sexStr获得,减少了业务代码里面的数据处理。
    • 实现结果
    带数组类型Model处理

    最后附上demo地址:MCModelDemo

    相关文章

      网友评论

      • 吴南北的禅:跟我的思路一样:smile:,但是我更喜欢用类方法生成model,另外楼主考虑过需要解档归档的model该怎么处理吗?

      本文标题:iOS 利用KVC进行数据转模型

      本文链接:https://www.haomeiwen.com/subject/cxgkwxtx.html