标签:blog http io ar os 使用 sp for on
字典转模型在iOS开发中属于非常常见的操作.
比较简单的方式是 KVC ,但是这样会有一个局限 ,就是 模型中的属性必须和字典中的完全匹配,否则,KVC将会报错.
手动编写代码虽然比较灵活,但是如果字典中数据量庞大,也会是一个糟糕的体验.
针对以上问题,利用runtime实现一个更加灵活的字典转模型.
1.为 NSObject建立一个分类
NSObject+GQRuntimeTool.h文件
#import <Foundation/Foundation.h> @interface NSObject (GQRuntimeTool) -(void)objectWithDictionary:(NSDictionary*)dict; @endNSObject+GQRuntimeTool.m文件
#import "NSObject+GQRuntimeTool.h" #import <objc/runtime.h> #import <objc/message.h> @implementation NSObject (GQRuntimeTool) -(void)objectWithDictionary:(NSDictionary*)dict { Class cls = [self class]; unsigned int count; //Ivar instance variable 就是类的成员属性 //通过运行时函数 获得 类内部的成员属性个数 放到 count 的地址 //返回说是一个指针 ,所指向的内存空间为 首个 Ivar 的内存地址,这个相当于数组名 Ivar *ivarArr = class_copyIvarList(cls, &count); //遍历数组( 数组名存放的是数组首地址,就是一个指针) for(int i =0;i<count;i++) { //把 Ivar 当成一个基本类型 比如 double 或者 int Ivar ivar = ivarArr[i]; //获取属性名 const char* name = ivar_getName(ivar); //获取属性类型 NSString* typeName =[NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)]; NSLog(@"%@",typeName); //发现 int 的类型是 i //1.将 c 字符串转换成 OC 的 NSMutableString * ocVaribaleName = [NSMutableString stringWithUTF8String:name]; //2.删除前面的 _ [ocVaribaleName deleteCharactersInRange:NSMakeRange(0, 1)]; // id_str //3.从字典取值的时候,使用的 key NSString *key = [ocVaribaleName copy]; //4.取值 id value = dict[key]; //5.将 id_str 转换成 setId_Str: NSString * setter = [self setterNameWithCString:name]; //6.使用运行时填充数据 if ([typeName isEqualToString:@"i"]) { int intValue =[value intValue]; objc_msgSend(self, NSSelectorFromString(setter),intValue); }else if([typeName isEqualToString:@"@\"NSString\""]) { NSString *str = [NSString stringWithFormat:@"%@",value]; objc_msgSend(self, NSSelectorFromString(setter),str); }//如果有其他类型,需要自己适配一下... /** 如果有其他类型,需要自己适配一下 int i double d bool B */ } } /** * 利用c字符串获得 setter方法的名字 * */ -(NSString*)setterNameWithCString:(const char*) cstr { char * strPointer = NULL; //此处不用 oc自带capitalizedString 的原因是发现他会将 id_str 大写成 Id_Str 而不是 Id_str CapicializeString(cstr, &strPointer); NSString * setter = [NSString stringWithUTF8String:strPointer]; free(strPointer); return setter; } void CapicializeString( const char * string,char ** s){ (*s) = malloc(strlen(string)+6); //拼出格式,并去掉 _ 现在的格式是 setid_str sprintf((*s),"set%s:",(string+1)); //大写 set后面的第一个字母 if(('a'<=(*s)[3])&&((*s)[3]<='z')) (*s)[3]-=32; } @end
GQModel.h
#import <Foundation/Foundation.h> #import "GQToy.h" @interface GQModel : NSObject /** * 唯一标识符 */ @property (nonatomic,copy)NSString *id_str; /** * 姓名 */ @property (nonatomic,copy)NSString *name; /** * 年龄 */ @property (nonatomic,assign)int age; /** * 性别 */ @property (nonatomic,copy)NSString *sex_str; @end
3.在controller中
- (void)viewDidLoad { [super viewDidLoad]; //这个字典在实际工作中,都是来自 JSon对象的,此处仅仅供测试 NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"22",@"id_str", @33,@"age", @"Grace",@"name", @"male",@"sex_str", nil]; GQModel * mo = [[GQModel alloc]init]; [mo objectWithDictionary:dict]; if (mo) { NSLog(@"mo的id是:%@\n",mo.id_str); NSLog(@"mo的名字是:%@\n",mo.name); NSLog(@"mo的年龄是:%d\n",mo.age); NSLog(@"mo的性别是:%@\n",mo.sex_str); } }
如果以后字典数据发生变化,只需要修改模型中的属性名即可.
是不是非常简单呢?
标签:blog http io ar os 使用 sp for on
原文地址:http://blog.csdn.net/quentingui/article/details/41870911