iOS开发——对象与字典互相转换

功能

通过自定义Model基类,实现:
1、将json字典转换成对象,无需考虑属性名称和字典键(key)的名称的关系,即可以自定义映射关系。也支持字典中自定义对象的赋值。
2、一行代码将对象转换为json字典。

使用

让自定义的Model类继承自CYZBaseModel即可。然后根据需要选择重写或者调用的方法。
字典转对象:
1、如果字典中的键的名称与对象的属性名称一样,则不需要重新任何方法,或者在attributeMapDictionary中返回nil即可。
2、如果字典中有任一键的名称与对象属性不一样,则需要自己建立映射字典,即在attributeMapDictionary中返回自己创建的一个字典类对象,该字典中,以属性名作为key,以“映射字典”(即传入字典)的键作为value。听起来可能比较绕,详情一看代码便知。
3、如果有自定义对象,则在setAttributeDictionary:中从字典中取出小字典并用它创建对象,然后赋值即可。
4、无论上述哪种情况,在创建你的自定义对象时都使用initWithDict:方法,传入dictionary便可以自动转成对象。

对象转字典:
调用方法dictionaryRepresentation即可

实现思路

主要用到的知识点就是反射,或者说objc的runtime知识。对象转字典,要获取到对象中的所有属性,然后把属性名和属性值存入字典即可。字典转对象,就是先根据自己定义的映射字典(map dictionary)将自己的属性名转换为待转换字典的key的名字,然后根据自己属性的名字获取setter方法,将待转换字典中取出来的值作为setter的参数调用就行了。

代码

对象转字典:

- (NSDictionary *)dictionaryRepresentation {
    unsigned int count = 0;
    //get a list of all properties of this class
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:count];

    NSDictionary *keyValueMap = [self attributeMapDictionary];

    for (int i = 0; i < count; i++) {
        NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
        id value = [self valueForKey:key];
        NSLog(@"key = %@, value = %@, value class = %@, changed Key = %@", key, value, NSStringFromClass([value class]), [keyValueMap objectForKey:key]);
        key = [keyValueMap objectForKey:key];
        //only add it to dictionary if it is not nil
        if (key && value) {
            [dict setObject:value forKey:key];
        }
    }

    free(properties);
    return dict;
}

字典转对象:

- (id)initWithDict:(NSDictionary *)aDict
{
    self = [super init];

    if (self) {
        //建立映射关系
        [self setAttributesDictionary:aDict];
    }

    return self;
}

- (NSDictionary *)attributeMapDictionary
{
    //子类需要重写的方法
    //NSAssert(NO, "You should override this method in Your Custom Class");
    return nil;
}

- (void)setAttributesDictionary:(NSDictionary *)aDict
{
    //获得映射字典
    NSDictionary *mapDictionary = [self attributeMapDictionary];

    //如果子类没有重写attributeMapDictionary方法,则使用默认映射字典
    if (mapDictionary == nil) {
        NSMutableDictionary *tempDict = [NSMutableDictionary dictionaryWithCapacity:aDict.count];
        for (NSString *key in aDict) {
            [tempDict setObject:key forKey:key];
        }
        mapDictionary = tempDict;
    }

    //遍历映射字典
    NSEnumerator *keyEnumerator = [mapDictionary keyEnumerator];
    id attributeName = nil;
    while ((attributeName = [keyEnumerator nextObject])) {
        //获得属性的setter
        SEL setter = [self _getSetterWithAttributeName:attributeName];
        if ([self respondsToSelector:setter]) {
            //获得映射字典的值,也就是传入字典的键
            NSString *aDictKey = [mapDictionary objectForKey:attributeName];
            //获得传入字典的键对应的值,也就是要赋给属性的值
            id aDictValue = [aDict objectForKey:aDictKey];

            //为属性赋值
            [self performSelectorOnMainThread:setter withObject:aDictValue waitUntilDone:[NSThread isMainThread]];
        }
    }
}

- (SEL)_getSetterWithAttributeName:(NSString *)attributeName
{
    NSString *firstAlpha = [[attributeName substringToIndex:1] uppercaseString];
    NSString *otherAlpha = [attributeName substringFromIndex:1];
    NSString *setterMethodName = [NSString stringWithFormat:@"set%@%@:", firstAlpha, otherAlpha];
    return NSSelectorFromString(setterMethodName);
}

下载

项目地址:https://github.com/YiZhuoChen/CYZBaseModel

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。