關於動態賦值已有很多帖子進行了詳細的說明,本帖就再也不討論,採用運行時數據轉模型是一種比較簡單的且複用性強的方法,然而使用時每每遇到由於數據結構複雜致使複合型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