iOS Runtime

对象模型转字典简析

2015-08-19  本文已影响115人  一念之见

引言

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

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

主要思路:

通过定义在<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];
}
上一篇下一篇

猜你喜欢

热点阅读