美文网首页iOS Runtime
对象模型转字典简析

对象模型转字典简析

作者: 一念之见 | 来源:发表于2015-08-19 01:13 被阅读115次

    引言

    大家或多或少都使用过音乐播放器App,播放器的底部工具条一般都是展示着当前播放的歌曲信息,以及拥有控制当前歌曲播放和暂停功能。无论我们在哪个界面点击了歌曲播放,底部工具条都会更新相应的信息,那么这要怎么实现呢?笔者思考之后,觉得设置通知是一个可行之法:当我们点击某个控件(比如tableViewCell)时,就在其响应方法中(tableView:didSelectRowAtIndexPath:)发布一个自定义名称的通知,该通知将点击播放的歌曲信息传递给监听者,然后设置底部工具条监听该通知,工具条就可以通过传递的参数来更新自己的显示。

    • 问题:通知传递的参数是(NSDictionary *)类型的,我们如何传递歌曲信息?(一般我们会将歌曲封装成模型,将歌曲信息作为歌曲的属性)。笔者试验过将对象直接转成字典来传递,结果遇到了难点无法解决,况且直接传递模型还存在一个缺陷,那就是监听该通知的文件都必须包含(#import)该模型对象。于是笔者又有了新的思考。
    • 解决方法:自定义分类方法,将模型属性抽取出来,分别转换成字典的键值对(属性 - 属性值 )

    以下为笔者搜索整理得到的分类,并做了详细说明:

    主要思路:

    通过定义在<objc/runtime.h>中的class_copyPropertyList方法获取属性数组的首元素地址,通过数组首元素地址遍历得到所有属性。其次,属性值的获取是通过KVC中的valueForKey方法,该方法同时可以将非对象类型(如BOOL, int等)转换成NSNumber。如果属性是数组、字典和对象类型,还有对属性值进行嵌套处理,最终将所有属性值转化成基本Objective-C类型。

    + (NSDictionary*)dictionaryWithObject:(id)obj
    {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        //定义存储属性数量的变量
        unsigned int propersCount;
        //指向属性数组的指针,可以访问数组中的所有属性,传入存储属性数量的变量的地址,该方法就会为其赋值
        objc_property_t *propers = class_copyPropertyList([obj class], &propersCount);
        //遍历属性
        for(int i = 0;i < propersCount; i++) {
            
            objc_property_t proper = propers[i];
            //获得字符串类型的属性名
            NSString *properName = [NSString stringWithUTF8String:property_getName(proper)];
            //通过KVC取得属性值
            id value = [obj valueForKey:properName];
            
            if(value == nil) {
              value = [NSNull null];
                
            } else { //如果属性值不为空,则判断属性值类型
                value = [self objectByPropertyValue:value];
            }
            [dict setObject:value forKey:properName];
        }
        return dict;
    }
    

    属性的嵌套处理

    + (id)objectByPropertyValue:(id)obj {
        //对NSString、NSNumber、NSNull类型的属性值不做处理,直接返回
        if([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSNull class]]) {
            return obj;
            //如果是数组类型,则遍历数组查看数组内部是否存在对象类型
        } else if([obj isKindOfClass:[NSArray class]]) {
    
            NSArray *objArray = obj;
            NSMutableArray *array = [NSMutableArray arrayWithCapacity:objArray.count];
            for(int i = 0;i < objArray.count; i++) {
                //嵌套
                [array setObject:[self objectByPropertyValue:[objArray objectAtIndex:i]] atIndexedSubscript:i];
            }
            //返回转化后的数组
            return array;
            //字典类型
        } else if([obj isKindOfClass:[NSDictionary class]]) {
            
            NSDictionary *objDict = obj;
            NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:[objDict count]];
            for(NSString *key in objDict.allKeys) {
        
                [dict setObject:[self objectByPropertyValue:[objDict objectForKey:key]] forKey:key];
            }     
             //返回转化后的字典
            return dict;
        }
        //对象类型等
        return [self objectByPropertyValue:obj];
    }
    

    相关文章

      网友评论

        本文标题:对象模型转字典简析

        本文链接:https://www.haomeiwen.com/subject/erzwqttx.html