YYModel 的使用场景和详解

作者: 凉秋落尘 | 来源:发表于2018-07-17 16:09 被阅读38次

    前言

    YYModel是YYKit的高效组件之一,在实际场景中的非常实用,运用于项目中使用MVC或MVVM架构时,使用model做数据处理。

    • 自动转换模型数据
    • 自动检测数据安全性,避免carch
    • 无需继承其他类,使用方便
    • 适用model各种数据加载运用场景

    在使用之前先展示一些YYModel比较常用的方法,后面会具体介绍用法

    // 字典转模型
    + (nullable instancetype)modelWithDictionary:(NSDictionary *)dictionary;
    // json转模型
    + (nullable instancetype)modelWithJSON:(id)json;
    // 模型转NSObject
    - (nullable id)modelToJSONObject;
    // 模型转NSData
    - (nullable NSData *)modelToJSONData;
    // 模型转json字符串
    - (nullable NSString *)modelToJSONString;
    // 模型深拷贝
    - (nullable id)modelCopy;
    // 判断模型是否相等
    - (BOOL)modelIsEqual:(id)model;
    // 属性数据映射,用来定义多样化数据时转换声明
    + (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper;
    // 属性自定义类映射,用来实现自定义类的转换声明
    + (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass;
    // 属性黑名单,该名单属性不转换为model
    + (nullable NSArray<NSString *> *)modelPropertyBlacklist;
    // 属性白名单,只有该名单的属性转换为model
    + (nullable NSArray<NSString *> *)modelPropertyWhitelist;
    // JSON 转为 Model 完成后,该方法会被调用,返回false该model会被忽略
    // 同时可以在该model中做一些,转换不能实现的操作,如NSDate类型转换
    - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;
    // Model 转为 JSON 完成后,该方法会被调用,返回false该model会被忽略
    // 同时可以在该model中做一些,转换不能实现的操作,如NSDate类型转换
    - (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic
    

    运用场景

    1、简单的数据交换

    YYModel最简单的使用,在正常的数据调用,创建一个model类YYPersonModel,增加几个属性。

    // YYPersonModel.h
    @interface YYPersonModel : NSObject
    
    @property (copy,   nonatomic) NSString *name;
    @property (assign, nonatomic) int age;
    @property (copy,   nonatomic) NSString *sex;
    
    @end
    

    接着在viewController导入<NSObject+YYModel.h>头文件,直接进行赋值就可以了,数据类型可可以是JSON/Dictionary,具体的可以看<NSObject+YYModel.h>给出的方法。

    // ViewController.m
    NSDictionary *dic = @{
                          @"name":@"张三",
                          @"age":@(12),
                          @"sex":@"男"
                        };
    // 将数据转模型
    YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
    // 将模型转数据
    NSDictionary *dics = [model modelToJSONObject];
    

    使用起来是不是变得特别方便,会自动根据key一一映射到对应的属性中对数据进行赋值,事实上使用只调用modelWithDictionary一个方法,剩下的YYModel会帮你处理里面的数据,自动进行安全性判断和值类型转换。

    2、自定义属性映射数据交换

    YYModel支持自定义的属性名进行映射,即数据的key和属性名可以是不相同。那么怎么才知道你自定义的属性名对应的是数据的哪个key呢?那就需要对自定义属性的映射进行映射声明。例如该例子中的personId:

    // YYPersonModel.h
    @interface YYPersonModel : NSObject
    
    @property (strong, nonatomic) NSNumber *personId;
    @property (copy,   nonatomic) NSString *name;
    @property (assign, nonatomic) int age;
    @property (copy,   nonatomic) NSString *sex;
    
    @end
    

    在YYPersonModel.m 重写yymodel的方法modelCustomPropertyMapper,返回设定的映射值,并且YYModel提供多个字段的映射。

    // YYPersonModel.m
    + (NSDictionary *)modelCustomPropertyMapper {
       // 将personId映射到key为id的数据字段
        return @{@"personId":@"id"};
       // 映射可以设定多个映射字段
       //  return @{@"personId":@[@"id",@"uid",@"ID"]};
    }
    

    最后依然通过像原来的数据那样,直接通过字典的方式进行模型转换,当key为id时,会自动给personId赋值,达到我们需要的效果。

    // ViewController.m
    NSDictionary *dic = @{
                          @"id":@"123",
                          @"name":@"张三",
                          @"age":@(12),
                          @"sex":@"男"
                          };
    YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
    NSLog(@"ID: %@",model.personId);
    NSDictionary *dics = [model modelToJSONObject];
    NSLog(@"ID: %@", dics[@"id"]);
    
    3、多样化的数据类型交换

    YYModel支持多样化的数据类型,甚至字典,数组等数据,如果不存在,则该model会自动设置为null,该例子提出使用NSArray和NSDictionary作为数据,效果依然一样

    // YYPersonModel.h
    @interface YYPersonModel : NSObject
    
    @property (strong, nonatomic) NSNumber *personId;
    @property (copy,   nonatomic) NSString *name;
    @property (assign, nonatomic) int age;
    @property (copy,   nonatomic) NSString *sex;
    @property (strong, nonatomic) NSArray *languages;
    @property (strong, nonatomic) NSDictionary *job;
    
    @end
    

    不得不说YYModel还是考虑很全面的,不仅支持各种类型数据,甚至考虑到获取到数据的层次关系并没有那么完美,那么这个时候该怎么做呢。例如该例子中的获取到sex,是嵌套在下一层,同样的我们也需要去声明:

    // YYPersonModel.m
    + (NSDictionary *)modelCustomPropertyMapper {
        return @{
                 @"personId":@"id",
                 @"sex":@"sexDic.sex" // 声明sex字段在sexDic下的sex
                 };
    }
    

    在数据中依然可以找到NSArray和NSDictionary和sexDic下的sex字段并转化为模型

    // ViewController.m
    NSDictionary *dic = @{
                          @"id":@"123",
                          @"name":@"张三",
                          @"age":@(12),
                          @"sexDic":@{@"sex":@"男"},
                          @"languages":@[
                                  @"汉语",@"英语",@"法语"
                                  ],
                          @"job":@{
                                  @"work":@"iOS开发",
                                  @"eveDay":@"10小时",
                                  @"site":@"软件园"
                                  }
                          };
    YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
    
    4、自定义类数据转换

    项目使用过程中,我们会涉及到多个model嵌套使用的情况,关于自定义类的声明,YYModel提供给我们另外一个方法modelContainerPropertyGenericClass。例如我们在属性中定义了YYEatModel作为类型。

    // YYPersonModel.h
    @interface YYEatModel : NSObject
    
    @property (copy, nonatomic)NSString *food;
    @property (copy, nonatomic)NSString *date;
    
    @end
    
    @interface YYPersonModel : NSObject
    
    @property (strong, nonatomic) NSNumber *personId;
    @property (copy,   nonatomic) NSString *name;
    @property (assign, nonatomic) int age;
    @property (copy,   nonatomic) NSString *sex;
    @property (strong, nonatomic) NSArray *languages;
    @property (strong, nonatomic) NSDictionary *job;
    @property (strong, nonatomic) NSArray <YYEatModel *> *eats;
    
    @end
    

    使用modelContainerPropertyGenericClass对赋值的key进行声明后,可直接赋值。

    // YYPersonModel.m
    + (NSDictionary *)modelCustomPropertyMapper {
        return @{
                 @"personId":@"id",
                 @"sex":@"sexDic.sex" // 声明sex字段在sexDic下的sex
                 };
    }
    // 声明自定义类参数类型
    + (NSDictionary *)modelContainerPropertyGenericClass {
        // value使用[YYEatModel class]或YYEatModel.class或@"YYEatModel"没有区别
        return @{@"eats" : [YYEatModel class]};
    }
    
    // ViewController.m
    NSDictionary *dic = @{
                          @"id":@"123",
                          @"name":@"张三",
                          @"age":@(12),
                          @"sexDic":@{@"sex":@"男"},
                          @"languages":@[
                                  @"汉语",@"英语",@"法语"
                                  ],
                          @"job":@{
                                  @"work":@"iOS开发",
                                  @"eveDay":@"10小时",
                                  @"site":@"软件园"
                                  },
                          @"eats":@[
                                  @{@"food":@"西瓜",@"date":@"8点"},
                                  @{@"food":@"烤鸭",@"date":@"14点"},
                                  @{@"food":@"西餐",@"date":@"20点"}
                                  ]
                          };
    YYPersonModel *model = [YYPersonModel modelWithDictionary:dic];
    for (YYEatModel *eat in model.eats) {
        NSLog(@"%@",eat.food);
    }
    
    5、YYModel数据的其他处理

    在转化过程中,YYModel提供了过滤的功能,可以将想要转换的属性或者不需要转换的属性加入到黑白名单中,通常不同时使用。

    // YYPersonModel.m 
    // 黑白名单不同时使用
    // 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
    + (NSArray *)modelPropertyBlacklist {
        return @[@"sex", @"languages"];
    }
    // 如果实现了该方法,则处理过程中不会处理该列表外的属性。
    + (NSArray *)modelPropertyWhitelist {
        return @[@"eats"];
    }
    

    有时候转换后的model并不是我们最终想要的,这个情况转换结束时YYModel提供了校验的接口,可以在该接口中,校验转换的结果返回false则直接忽略该model,同时可以在该接口中处理转换过程中,不能处理的数据。

    // YYPersonModel.m 
    // 当 JSON 转为 Model 完成后,该方法会被调用。
    - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
        // 可以在这里处理一些数据逻辑,如NSDate格式的转换
        return YES;
    }
    
    // 当 Model 转为 JSON 完成后,该方法会被调用。
    - (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
        return YES;
    }
    

    最后在Model使用过程中,往往会遇到一个深拷贝的问题,为了不改变原model的数据,YYModel也提供了一个接口实现深拷贝。至于不懂深拷贝的同学可以先去网上了解一下

    // ViewController.m
    // 深拷贝model
    YYPersonModel *model2 = [model modelCopy];
    

    总结

    到这里为止,关于YYModel的详细使用方法已经写完,基本上所有的使用场景都会在,如果有什么疑问可以给我留言。

    相关文章

      网友评论

      • 简书花花:YYModel 很久没更新了,纠结用YY还是Json

      本文标题:YYModel 的使用场景和详解

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