iOS中字典轉(zhuǎn)模型的方法

作品鏈接:http://www.itdecent.cn/users/1e0f5e6f73f6/top_articles

1 自動(dòng)打印屬性字符串分類

  • 提供一個(gè)分類,專門(mén)根據(jù)字典生成對(duì)應(yīng)的屬性字符串。
@implementation NSObject (Property)

+ (void)PH_createPropertyCodeWithDict:(NSDictionary *)dict
{
    NSMutableString *strM = [NSMutableString string];
    // 遍歷字典
    [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull propertyName, id  _Nonnull value, BOOL * _Nonnull stop) {
        NSLog(@"%@,%@",propertyName,[value class]);

        NSString *code;
        if ([value isKindOfClass:NSClassFromString(@"__NSCFString")]) {
            code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSString *%@;",propertyName]
            ;
        } else if ([value isKindOfClass:NSClassFromString(@"__NSCFNumber")]){
            code = [NSString stringWithFormat:@"@property (nonatomic, assign) int %@;",propertyName]
            ;
        }else if ([value isKindOfClass:NSClassFromString(@"__NSCFArray")]){
            code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSArray *%@;",propertyName]
            ;
        }else if ([value isKindOfClass:NSClassFromString(@"__NSCFDictionary")]){
            code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSDictionary *%@;",propertyName]
            ;
        } else if ([value isKindOfClass:NSClassFromString(@"__NSCFBoolean")]){
            code = [NSString stringWithFormat:@"@property (nonatomic, assign) BOOL %@;",propertyName]
            ;
        }
        [strM appendFormat:@"\n%@\n",code];
    }];

    NSLog(@"%@",strM);
}
@end

2 字典轉(zhuǎn)模型的方式一:KVC

@implementation Status


+ (instancetype)statusWithDict:(NSDictionary *)dict
{
    Status *status = [[self alloc] init];

    [status setValuesForKeysWithDictionary:dict];

    return status;

}

@end

  • KVC字典轉(zhuǎn)模型弊端:必須保證,模型中的屬性和字典中的key一一對(duì)應(yīng)。
    • 如果不一致,就會(huì)調(diào)用[<Status 0x7fa74b545d60> setValue:forUndefinedKey:]
      報(bào)key找不到的錯(cuò)。
    • 分析:模型中的屬性和字典的key不一一對(duì)應(yīng),系統(tǒng)就會(huì)調(diào)用setValue:forUndefinedKey:報(bào)錯(cuò)。
    • 解決:重寫(xiě)對(duì)象的setValue:forUndefinedKey:,把系統(tǒng)的方法覆蓋,
      就能繼續(xù)使用KVC,字典轉(zhuǎn)模型了。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{

}

3 字典轉(zhuǎn)模型的方式二:Runtime

  • KVC:遍歷字典中所有key,去模型中查找有沒(méi)有對(duì)應(yīng)的屬性名
  • runtime:遍歷模型中所有屬性名,去字典中查找

1.思路與步驟

<!--* 思路:利用運(yùn)行時(shí),遍歷模型中所有屬性,根據(jù)模型的屬性名,去字典中查找key,取出對(duì)應(yīng)的值,給模型的屬性賦值。-->
<!--* 步驟:提供一個(gè)NSObject分類,專門(mén)字典轉(zhuǎn)模型,以后所有模型都可以通過(guò)這個(gè)分類轉(zhuǎn)。-->

2.分類

+ (instancetype)PH_modelWithDict:(NSDictionary *)dict
{
    // 創(chuàng)建對(duì)應(yīng)類的對(duì)象
    id objc = [[self alloc] init];

    // runtime:遍歷模型中所有成員屬性,去字典中查找
    // 屬性定義在哪,定義在類,類里面有個(gè)屬性列表(數(shù)組)

    // 遍歷模型所有成員屬性
    // ivar:成員屬性
    // class_copyIvarList:把成員屬性列表復(fù)制一份給你
    // Ivar *:指向Ivar指針
    // Ivar *:指向一個(gè)成員變量數(shù)組
    // class:獲取哪個(gè)類的成員屬性列表
    // count:成員屬性總數(shù)

    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList(self, &count);
    for (int i = 0; i < count; i++) {
        // 獲取成員屬性
        Ivar ivar = ivarList[i];
        // 獲取成員名
        NSString *propertyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        //成員屬性類型
        NSString *propertyType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        //獲取key
        NSString *key = [propertyName substringFromIndex:1];
        //獲取字典的value
        id value = dict[key];
        // 給模型的屬性賦值
        // value:字典的值
        // key:屬性名

// user:NSDictionary
        //** '二級(jí)轉(zhuǎn)換'**
          // 值是字典,成員屬性的類型不是字典,才需要轉(zhuǎn)換成模型

        if ([value isKindOfClass:[NSDictionary class]] && ![propertyType containsString:@"NS"]) {
            // 需要字典轉(zhuǎn)換成模型
            // 轉(zhuǎn)換成哪個(gè)類型

            // @"@\"User\"" User
            NSRange range = [propertyType rangeOfString:@"\""];
            propertyType = [propertyType substringFromIndex:range.location + range.length];
            // User\"";

            range = [propertyType rangeOfString:@"\""];
            propertyType = [propertyType substringFromIndex:range.location];
            // 字符串截取

            // 獲取需要轉(zhuǎn)換類的類對(duì)象
            Class modelClass = NSClassFromString(propertyType);
            if (modelClass) {
                value = [modelClass PH_modelWithDict:value];
            }

        }

<!-- 三級(jí)轉(zhuǎn)換:NSArray中也是字典,把數(shù)組中的字典轉(zhuǎn)換成模型.-->
        // 判斷值是否是數(shù)組
        if ([value isKindOfClass:[NSArray class]]) {
            //判斷對(duì)應(yīng)類有沒(méi)有實(shí)現(xiàn)字典數(shù)組轉(zhuǎn)模型數(shù)組的協(xié)議
            if ([self respondsToSelector:@selector(PH_arrayContainModelClass)]) {

                // 轉(zhuǎn)換成id類型,就能調(diào)用任何對(duì)象的方法
                id idSelf = self;

                // 獲取數(shù)組中字典對(duì)應(yīng)的模型
                NSString *type =  [idSelf PH_arrayContainModelClass][key];

                // 生成模型
                Class classModel = NSClassFromString(type);
                NSMutableArray *arrM = [NSMutableArray array];

                // 遍歷字典數(shù)組,生成模型數(shù)組
                for (NSDictionary *dict in value) {
                    // 字典轉(zhuǎn)模型
                    id model = [classModel PH_modelWithDict:dict];
                    [arrM addObject:model];
                }
                // 把模型數(shù)組賦值給value
                value = arrM;
            }
        }


        if (value) {
            // kvc賦值:不能傳空
            [objc setValue:value forKey:key];
        }
        NSLog(@"%@",key);
        NSLog(@"%@,%@",propertyName,propertyType);
    }

    return objc;
}

3.轉(zhuǎn)換

- (void)viewDidLoad {
    [super viewDidLoad];

    // 解析
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
    NSArray *dictArr = dict[@"statuses"];

    // 設(shè)計(jì)模型屬性代碼

    NSMutableArray *statuses = [NSMutableArray array];

    for (NSDictionary *dict in dictArr) {
        // 字典轉(zhuǎn)模型
        Status *status = [Status PH_modelWithDict:dict];
        [statuses addObject:status];
    }
    NSLog(@"%@",statuses);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 對(duì)于從事 iOS 開(kāi)發(fā)人員來(lái)說(shuō),所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢(mèng)夜繁星閱讀 3,812評(píng)論 7 64
  • 一 快速生成@property 1 當(dāng)我們需要用模型去實(shí)現(xiàn)一個(gè)比較小的功能的時(shí)候,由于我們需要對(duì)plist文件進(jìn)行...
    莫許閱讀 708評(píng)論 1 1
  • 一個(gè)基佬,從開(kāi)始發(fā)現(xiàn)自己喜歡男人,他所理解的男人就是直男那樣。后來(lái)歷盡劫難發(fā)現(xiàn)直男并不屬于自己,目標(biāo)就開(kāi)始轉(zhuǎn)向基佬...
    謝子德閱讀 1,279評(píng)論 2 1
  • 01 有多少人體驗(yàn)著被生活綁架的感覺(jué)?我就是其中一名。因?yàn)楦咝?,我守著毫無(wú)提升空間,卻壓力山大的工作不敢放手。為了...
    指尖的山茶花閱讀 1,553評(píng)論 2 12
  • 零距離朋友文很清高。說(shuō)她清高沒(méi)有任何諷刺的意味,是說(shuō)在這個(gè)以物質(zhì)為王道的社會(huì)里,清高的她從不會(huì)和老板講條件,老板讓...
    云在天上飄閱讀 649評(píng)論 0 2

友情鏈接更多精彩內(nèi)容