XZ_iOS之Runtime使用运行时实现字典转模型和关联对象

来源:互联网 发布:win10平板相关软件 编辑:程序博客网 时间:2024/05/16 07:22

使用运行时实现字典转模型和关联对象objc_get/setAssociatedObject()

创建一个类Person,重写它的description方法,打印出它的属性值。

XZPerson.m
@implementation XZPerson

- (NSString *)description {
   NSArray *keys =@[@"name",@"age",@"weight",@"sex"];
   
   return [selfdictionaryWithValuesForKeys:keys].description;
}
@end

NSObject+XZRuntime.h
#import<Foundation/Foundation.h>

@interface NSObject (XZRuntime)
//获取类的属性列表
// @return类的属性列表数组
+ (NSArray *)xz_objcProperties;

//给定一个字典,创建 self类对应的对象
// @param dict字典  @return对象
+ (instancetype)xz_objWithDic:(NSDictionary *)dict;
@end

NSObject+XZRuntime.m
#import"NSObject+XZRuntime.h"
#import<objc/runtime.h>

@implementation NSObject (XZRuntime)

//所有字典转模型框架的核心算法 //运行时字典转模型的基本方法的实现
+ (instancetype)xz_objWithDic:(NSDictionary *)dict {
   //实例化对象
   id object = [[selfalloc]init];
   
   //使用字典,设置对象信息
   // 1>获得 self 的属性列表
   NSArray *proList = [selfxz_objcProperties];
   // 2>遍历字典
    [dictenumerateKeysAndObjectsUsingBlock:^(id _Nonnull key,id _Nonnull obj,BOOL *_Nonnull stop) {
       NSLog(@"key %@ ---- value %@",key,obj);
       // 3>判断 key 是否存在 proList
       if ([proListcontainsObject:key]) {
           //说明属性存在,可以使用 ‘KVC’设置数值
            [objectsetValue:objforKey:key];
        }
    }];
   
   return object;
}

constchar *kPropertiesListKey ="CZPropertiesListKey";
+ (NSArray *)xz_objcProperties {
   //因为属性列表在运行的过程中不会改变,所以使用运行时关联对象,提高效率
   //①、从关联对象中获取对象属性,如果有,直接返回!
   /**
    获取关联对象 --动态添加的属性
    参数1:对象:self 参数2:动态属性的 key
    返回值:动态添加的属性值’ id
     */
   NSArray *ptyList =objc_getAssociatedObject(self,kPropertiesListKey);
   if (ptyList !=nil) {
       return ptyList;
    }
   
   //使用运行时获取对象的属性数组
   // class_copyIvarList  Ivar成员变量
   // class_copyPropertyList  Property属性
   // class_copyMethodList  Method方法
   // class_copyProtocolList  Protocol协议
   //参数一:要获取的类参数二:类属性的个数指针
   //返回值:所有属性的'数组'C语言中,数组的名字,就是指向第一个元素的地址
   unsignedint outCount =0;
   //调用运行时方法,取得类的属性列表
   objc_property_t *proList =class_copyPropertyList([selfclass], &outCount);
   NSLog(@"属性列表的数量 %d",outCount);
   
   NSMutableArray *array = [NSMutableArrayarray];
   //遍历所有的属性
   for (unsignedint i =0; i < outCount; i++) {
       //1.从数组中取得属性 C语言的结构体指针,通常不需要'*'
       objc_property_t pty = proList[i];
       
       // 2.pty中获得属性的名称
       constchar *cName =property_getName(pty);
       //C语言字符串转化成OC字符串
       NSString *name = [NSStringstringWithCString:cNameencoding:NSUTF8StringEncoding];
       // 3.属性名称添加到数组
        [arrayaddObject:name];
    }
   
   // retain/create/copy需要 release,点击option + click查看
   //释放数组
   free(proList);
   
   //②、到此为止,对象的属性数组已经获取完毕,利用关联对象,动态添加属性
   /**
    参数
     1.对象 self [OC class也是一个特殊的对象]
     2.动态添加的属性的 key,获取值的时候也使用
     3.动态添加的属性值
     4.对象的引用关系
     */
   objc_setAssociatedObject(self,kPropertiesListKey, array.copy,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
   return array.copy;
}

@end

XZRunTimeController.m
//字典转模型
   XZPerson *person = [XZPersonxz_objWithDic:@{
                                                @"name":@"zhangsan",
                                                @"age":@18,
                                                @"sex":@"female",
                                                @"height":@1.8,
                                                @"weight":@100,
                                                }];

阅读全文
0 0
原创粉丝点击