关于动态赋值已有很多帖子进行了详细的说明,本帖就再也不讨论,采用运行时数据转模型是一种比较简单的且复用性强的方法,然而使用时每每遇到由于数据结构复杂致使复合型json没法彻底转化的问题。
本帖主要研究了运行时对模型属性的子属性如何作到循环赋值,第一次发帖若有措辞不当还请见谅。json
废话很少说,上代码:
好比有时咱们遇到了以下复合型需求的model,网上有不少根据json自动生成model的开源工具用起来很方便,这里使用到的是WHC_DataModelFactory;数组
#import <Foundation/Foundation.h> @interface books :NSObject @property (nonatomic , copy) NSString * book_pic_url; @property (nonatomic , copy) NSString * book_score; @property (nonatomic , copy) NSString * book_summary; @property (nonatomic , strong) NSNumber * book_id; @property (nonatomic , copy) NSString * author_name; @property (nonatomic , copy) NSString * book_read_url; @property (nonatomic , copy) NSString * book_name; @property (nonatomic , strong) NSNumber * is_member_book; @end @interface NRmodel :NSObject @property (nonatomic , strong) NSArray * books; @property (nonatomic , copy) NSString * H5bookShelf; @property (nonatomic , copy) NSString * h5Address; @end
这个模型中明显是模型中有一个数组,数组装的是子属性books;(因为通常json不会出现多层数组紧邻嵌套的状况,因此本文中未对该状况作循环赋值);
通常状况下,咱们用到的运行时遍历字典key进行赋值时会致使该数组存放的是仍一个个字典。
怎么才能让数组中放的是地址(对象)而非字典呢,咱们首先须要分辨出字典的value,当其为数组时特殊处理,建立以key值为类名的对象,而后遍历数组对数组内数据结构
的字典进行第二次运行时赋值操做,代码以下:工具
+(id)ccObjectFromClass:(Class)theClass dict:(NSDictionary *)dict { if (NO == [dict isKindOfClass:[NSDictionary class]]) { return nil; } //初始化对象 id object = [[theClass alloc] init]; for (NSString *key in [dict allKeys]) { id value = [dict objectForKey:key]; NSString * propertyString = [NSString stringWithFormat:@"%@%@",[[key uppercaseString] substringToIndex:1],[key substringFromIndex:1]]; NSString *propertySetSel = [NSString stringWithFormat:@"set%@:",propertyString]; SEL setterSEL = NSSelectorFromString(propertySetSel); SEL getterSEL = NSSelectorFromString(key); //当字典的对应value也是字典时触发本方法的循环给属性的属性赋值 if ([value isKindOfClass:[NSDictionary class]]&&[object respondsToSelector:getterSEL]) { Class theClass1 = NSClassFromString(key); id tempProp =[[theClass1 alloc]init]; tempProp =[NSObject ccObjectFromClass:[theClass1 class] dict:value]; [object performSelector:setterSEL withObject: tempProp] ; } //当字典的对应value是数组时遍历数组,对value的每个子字典进行本方法的循环给属性数组内包含的属性赋值 else if ([value isKindOfClass:[NSArray class]]&&[object respondsToSelector:getterSEL]){ NSMutableArray * arr = [NSMutableArray array]; for (id contain in value) { if ([contain isKindOfClass:[NSArray class]]) { [object performSelector:setterSEL withObject:value]; }else if([contain isKindOfClass:[NSDictionary class]]){ Class theClass2 = NSClassFromString(key); id tempProp =[[theClass2 alloc]init]; tempProp =[NSObject ccObjectFromClass:[theClass2 class] dict:contain]; NSLog(@"%@",tempProp); [arr addObject:tempProp]; } [object performSelector:setterSEL withObject:arr]; } } if ([object respondsToSelector:setterSEL]) { const char *propertyName = [key cStringUsingEncoding:NSUTF8StringEncoding]; objc_property_t properties = class_getProperty(theClass, propertyName); if (properties) { const char *propertyAtt = property_getAttributes(properties); NSString *propertyAttS = [NSString stringWithCString:propertyAtt encoding:NSUTF8StringEncoding]; if ([propertyAttS rangeOfString:@"NSNumber"].length > 0) { if ([value isKindOfClass:[NSString class]]) { NSNumber *newValue = @([value doubleValue]); value = newValue; } } } if ([value isKindOfClass:[NSString class]]) { if (![value isEqualToString:nullString]) { [object performSelector:setterSEL withObject:value]; } } else if (![value isEqual:[NSNull null]] && ![value isKindOfClass:[NSArray class]] && ![value isKindOfClass:[NSDictionary class]]) { [object performSelector:setterSEL withObject:value]; } } } return [object autorelease]; }
上述代码,分别对数组和字典相互嵌套,字典与字典嵌套的json进行了额外处理,最终目的是使用model时无需二次赋值,直接获取属性的子属性便可进行操做,好比字典与字典相互嵌套便可用model的点语法获取属性的属性使操做更加便捷。
以上,谢谢
新人发贴,大神们手下留情atom