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

本文介绍如何在Objective-C中实现字典到模型对象的转换,并利用运行时特性提高性能。通过具体示例展示了如何创建并重写Person类的description方法来打印其属性值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

XZPerson.m
@implementation XZPerson

- (NSString *)description {
    NSArray *keys = @[@"name",@"age",@"weight",@"sex"];
   
    return [self dictionaryWithValuesForKeys: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 = [[self alloc] init];
   
    // 使用字典,设置对象信息
    // 1>获得 self 的属性列表
    NSArray *proList = [self xz_objcProperties];
    // 2>遍历字典
    [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSLog(@"key %@ ---- value %@",key,obj);
        // 3>判断 key 是否存在 proList
        if ([proList containsObject:key]) {
            // 说明属性存在,可以使用 ‘KVC’ 设置数值
            [object setValue:obj forKey:key];
        }
    }];
   
    return object;
}

const char *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语言中,数组的名字,就是指向第一个元素的地址
    unsigned int outCount = 0;
    // 调用运行时方法,取得类的属性列表
    objc_property_t *proList = class_copyPropertyList([self class], &outCount);
    NSLog(@"属性列表的数量 %d",outCount);
   
    NSMutableArray *array = [NSMutableArray array];
    // 遍历所有的属性
    for (unsigned int i = 0; i < outCount; i++) {
        //1.从数组中取得属性 C语言的结构体指针,通常不需要'*'
        objc_property_t pty = proList[i];
       
        // 2.pty中获得属性的名称
        const char *cName = property_getName(pty);
        // C语言字符串转化成OC字符串
        NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
        // 3.属性名称添加到数组
        [array addObject: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 = [XZPerson xz_objWithDic:@{
                                                 @"name":@"zhangsan",
                                                 @"age":@18,
                                                 @"sex":@"female",
                                                 @"height":@1.8,
                                                 @"weight":@100,
                                                 }];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值