在我们的日常开发中需要对加载的一些本地数据例如plist、json等文件中的数据进行模型转化,而苹果也为我们提供了一种非常方便的键值转换方式KVC。然而KVC在某些情况下并不能保存数据的转换成功,比如必须保证模型的属性个数大于等于字典个数,也要必须属性名称与字典的key相同等。所以这次我们假设下属性名称与字典中的key不一致的时候转换方法。
首先我们还是先要尝试下使用KVC的方式来解决这个问题
模型如下:
@property (nonatomic, strong) NSString *title; @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *ID;
{ "title" : "顺平侯", "name" : "赵云", "id" : "sph" }, { "title" : "恒侯", "html" : "张飞", "id" : "hh" }, { "title" : "威侯", "html" : "马超", "id" : "wh" }, { "title" : "刚侯", "html" : "黄忠", "id" : "gh" }, { "title" : "寿亭侯", "html" : "关羽", "id" : "sth" }
从上面的数据对比我们不难发现,因为在OC中的id是关键字所有我们使用ID来替代,但是这样的话就不能直接使用KVC,所以我们需要进行相应的处理来继续使用我们的KVC转换模型。代码如下:
首先在模型.h文件中更新一下代码,提供一个类方法进行模型转换:
@property (nonatomic, strong) NSString *title; @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *ID;+(instancetype) heroDict:(NSDictionary*) dict;
+ (instancetype)itemWithDict:(NSDictionary *)dict { HeroItem *hero = [[self alloc]init];[item setValuesForKeysWithDictionary:dict]; return item; }
- (void)setValue:(id)value forKey:(NSString *)key{ //因为已经知道要修改的key所以可以直接判定相等 if ([key isEqualToString:@"id"]) { //进行替换 [self setValue:value forKeyPath:@"ID"]; }else{ //抛回父类处理 [super setValue:value forKey:key]; } }
#import <objc/runtime.h>
+ (instancetype)objcWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict{}
(instancetype)objcWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict{ id objc = [[self alloc] init]; // 遍历模型中属性 unsigned int count = 0; Ivar *ivars = class_copyIvarList(self, &count); for (int i = 0 ; i < count; i++) { Ivar ivar = ivars[i]; // 属性名称 NSString *ivarName = @(ivar_getName(ivar)); ivarName = [ivarName substringFromIndex:1]; id value = dict[ivarName]; // 模型中属性名对应字典中的key if (value == nil) { if (updateDict) { NSString *keyName = updateDict[ivarName]; value = dict[keyName]; } } [objc setValue:value forKeyPath:ivarName]; } return objc; }
+ (instancetype)itemWithDict:(NSDictionary *)dict{ //调用方法,updateDict中的数据即为需要替换的数据 HeroItem *item = [HeroItem objcWithDict:dict updateDict:@{@"ID":@"id"}]; return item; }
使用jastor
如果有jastor这个库,也会方便很多现在就基本的用法做个介绍。
假如我们有如下这么一个类
#import <Foundation/Foundation.h> #import "Jastor.h"@interface DeviceEntity : Jastor
@property (nonatomic,strong) NSNumber *isonline; @property (nonatomic,strong) NSNumber *isopen; @property (nonatomic,copy) NSString *brand;
@end
#import "DeviceEntity.h"
@implementation DeviceEntity
@synthesize isopen,isonline,brand;
@end
#import <Foundation/Foundation.h> #import "Jastor.h" #import "DeviceEntity.h"
@interface UserDevicesEntity : Jastor
@property (nonatomic,strong) NSNumber *closecount; @property (nonatomic,strong) NSNumber *opencount; @property (nonatomic,copy) NSString *success; @property (nonatomic,strong) NSArray *items;
@end
#import "UserDevicesEntity.h" #import "DeviceEntity.h"
@implementation UserDevicesEntity
@synthesize closecount,opencount,success,items;
+ (Class) items_class { return [DeviceEntity class]; }
@end
在调用服务的时候,对方一般都会返回一个json,我们要做的就是根据这个字符串实例化一个NSDictionary出来,然后就可以根据这个NSDictionay实例化相应的模型了,比我们直接解析这个字符串方便多了,代码如下:
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"1",@"isonline",@"1",@"isopen",@"brand1",@"brand", nil]; DeviceEntity *device = [[DeviceEntity alloc] initWithDictionary:dictionary];
NSLog(@"device's brand is %@",device.brand); NSLog(@"device's isonline is %d",[device.isonline intValue]); NSLog(@"device's isopen is %d",[device.isopen intValue]);
2014-02-17 22:36:37.602 objc-grammar-learing[819:f803] device's brand is brand1 2014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isonline is 1 2014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isopen is 1
看看是不是方便很多,当然上面只是很简章的模型,一般来讲,真实项目中的模型肯定比这复杂,比如一对一,一对多等等,在官网上面都有相应例子可以参考。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。