关于动态赋值已有不少帖子进行了详细的说明,本帖就不再讨论,采用运行时数据转模型是一种比较简单的且复用性强的方法,然而使用时往往遇到因为数据结构复杂导致复合型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的点语法获取属性的属性使操作更加便捷。
以上,谢谢
新人发贴,大神们手下留情
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。