採用運行時進行復合型數據轉模型

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

相關文章
相關標籤/搜索