iOS 利用KVC进行数据转模型
2017-12-15 本文已影响429人
calary
前言
最近公司要求做一个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获得,减少了业务代码里面的数据处理。
- 实现结果
最后附上demo地址:MCModelDemo