runtime笔记 之 字典转模型

作者: ZYiDa | 来源:发表于2018-04-20 16:54 被阅读6次

    先看例子

    Model
    #import <Foundation/Foundation.h>
    
    @interface NSObject (Hook)
    
    + (instancetype)modelWithDict:(NSDictionary *)dict;
    
    @end
    
    #import "TestModel.h"
    
    @implementation TestModel
    
    @end
    
    NSObject的分类
    #import <Foundation/Foundation.h>
    
    @interface NSObject (Hook)
    
    + (instancetype)modelWithDict:(NSDictionary *)dict;
    
    @end
    
    #import "NSObject+Hook.h"
    #import <objc/runtime.h>
    
    const char * kPropertyListKey = "PropertyListKey";
    
    @implementation NSObject (Hook)
    
    + (NSArray *)getPropertyList{
        //获取关联对象,根据关联值的 key 取出关联值,如果有值就返回,没有值,则继续。
        NSArray *propertylistArr = objc_getAssociatedObject([self class], kPropertyListKey);
        
        //如果有值,直接返回
        if (propertylistArr) {
            return propertylistArr;
        }
        
        //类属性的个数
        unsigned int listOutCount = 0;
        
        //注意 class_copyPropertyList 中是 copy 需要 release 释放一下(retain copy create--release)
        objc_property_t *propertyList = class_copyPropertyList(self, &listOutCount);
        
        NSMutableArray *temArray = [NSMutableArray array];
        for (unsigned int i = 0; i < listOutCount; i++) {
            
            //获取属性
            objc_property_t property = propertyList[i];
            
            //获取属性名称
            const char *name = property_getName(property);
            
            //名称转化为 OC 字符串
            NSString *propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
            
            [temArray addObject:propertyName];
        }
        
        //设置关联对象,给 NSObject 分类动态添加属性,也就是 model 类的属性
        objc_setAssociatedObject(self, kPropertyListKey, [temArray copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        
        //propertyList是通过 copy 方式获得的,需要释放。
        free(propertyList);
        
        return [temArray copy];
    }
    + (instancetype)modelWithDict:(NSDictionary *)dict{
        
        id objc = [[self alloc]init];
        
        NSArray *properties = [self getPropertyList];
        
        [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            if ([properties containsObject:key]) {
                [objc setValue:obj forKey:key];
            }
        }];
        
        return objc;
    }
    @end
    
    测试
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSDictionary *dic = @{
                              @"name":@"lilei",
                              @"age":@18,
                              };
        TestModel *model = [TestModel modelWithDict:dic];
        NSLog(@"== model:%@---%ld---%ld==",model.name,model.age,model.height);
        
    }
    

    class_copyPropertyList的说明

    /** 
     * 描述由类声明的属性。
     * 
     * @param cls 你想要检查(获取)属性列表的类。
     * @param outCount 属性列表的数组的个数指针
     *  If \e outCount is \c NULL, the length is not returned.        
     * 
     * @return 
      *描述由类声明的属性的类型为objc_property_t的指针数组。
      *不包括由超类声明的任何属性。
      *该数组包含outCount指针,后跟NULL结束符。
      *你必须用free()释放数组。
      *如果cls声明没有属性,或cls为零,则返回NULL,outCount为0。
     */
    OBJC_EXPORT objc_property_t _Nonnull * _Nullable
    class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount)
        OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
    

    与此类似的还有

     /* 成员变量:
         * class_copyIvarList(__unsafe_unretained Class cls, unsigned int *outCount)
         * 方法:
         * class_copyMethodList(__unsafe_unretained Class cls, unsigned int *outCount)
         * 属性:
         * class_copyPropertyList(__unsafe_unretained Class cls, unsigned int *outCount)
         * 协议:
         * class_copyProtocolList(__unsafe_unretained Class cls, unsigned int *outCount)
         */
    

    学习一个类的最好方式就是去查看它的API 文档,共勉。


    相关文章

      网友评论

        本文标题:runtime笔记 之 字典转模型

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