Runtime应用--反射机制

本文我们再来介绍一下Runtime的第二个应用:反射机制

字典转类型(反射机制)

场景:

App发起网络请求后,后端返回了一大串JSON 数据

我们需要将这个字典转化为我们定义的对象模型 Model ,比如User对象,Product对象,以便在代码中使用user.name而不是dict[@"name"]

  • 不使用 Runtime :

    • 在 Codable 引入前,在 OC 时代,你需要手动编写代码,假设一个模型有 20 个属性,你就要写 20 行代码;

    • 如果后端增加了一个字段,或者你有 100 个不同的 Model 类,这种手动编写不仅效率低,而且容易拼写错误。

      // 传统笨办法
      User *user = [[User alloc] init];
      user.name = dict[@"name"];
      user.age = dict[@"age"];
      user.address = dict[@"address"];
      // ... 还有17行 ...

  • 使用Runtime:

    • 写一个通用的方法objectWithDict:,无论什么 Model 类都能调用它,能自动把字典的值填入对象的属性中。

原理:

利用 Runtime 的反射机制------指程序在运行期间可以检查自身结构的能力

核心思路:

  • 利用 Runtime 的class_copyIvarList函数,在运行时动态获取当前类中定义了哪些成员变量ivar
  • 遍历这些变量名_name,_age
  • 处理变量名(去掉开头的下划线_),使其变成字典里的Key(比如name,age
  • 拿着 Key 去字典里找对应的值
  • 利用 KVC,将找到的值赋值给对象

具体代码举例

main函数与输出结果

与Codable的区别

在纯Swift开发中,我们网络请求数据转换通常会使用Codable,是目前最标准、最推荐、也是最方便的方法。

同样的数据解析代码如下所示。

那么两者的区别有什么呢?

1.类型的容错能力

例如后端定义了一个字段是数字Int,但是返回了一个字符串 "123"。

  • Codable(强类型安全 ):
    • 会直接报错,解析失败,整个 Model 都会解析为nil,并抛出异常typeMismatch
    • 需要开发者自定义方法解决
  • Runtime 库(运行时动态检查与隐式转换 ):
    • 解析成功
    • Runtime 库通常会在内部做类型检测和转换逻辑。发现属性是int,但字典里是NSString,会自动把"123"转成数字123赋值进去

2.处理多层嵌套的数据结构

  • Codable(全自动递归
    • 利用 Swift 强大的泛型和编译器支持
    • 对于嵌套数组,编译器在编译阶段就已经知道了数组内元素的具体类型。解析时,Codable 会自动递归调用相关解析方法,无需额外配置。
  • Runtime库(需手动配置
    • Runtime 在运行时能识别出属性时 NSArray,但不知道数据里面装的是什么类型
    • 必须书动编写映射代码,显示告诉Runtime,数组里面的元素类型是什么;如果忘记配置,数据会被解析为原始的NSDictionary,导致后续调用崩溃

3.性能

实际上,基于 Runtime 优化的 C 语言库往往比 Swift 的 JSONDecoder 更快。

  • Codable(安全优先 ):
    • Swift 的 JSONDecoder 为了安全,在底层做了大量的类型检查、中间层封装和错误抛出机制
  • Runtime(效率优先 ):
    • 像 YYModel 这种库,直接操作内存地址,利用 C 语言的高效性直接赋值,逃过了很多安全检查,在处理海量数据时,速度更优于原生 Codable

4.对象生命周期

例如你有一个已经存在的 User 对象,现在网络请求回来了新的数据,你只想更新这个对象的部分属性。

  • Codable(只负责创建 ):
    • Decodable 协议的核心是 init(from:)
    • 只能初始化并返回一个新的实例。这意味着,你会得到一个新的User实例,然后你需要手动把新实例的值一个一个赋给老实例。
  • Runtime(支持热更新 ):
    • 可以直接修改内存,不需要调用init
    • Runtime可以遍历字典,利用KVC,把数据直接"灌入"到一个已经存在的对象实例中。
相关推荐
G皮T1 天前
【Java】Java 运行时数据区域(一):名词概念
java·jvm·runtime·运行时·运行时数据区域
RollingPin10 天前
iOS 内存管理之 autoreleasePool
ios·内存管理·runtime·autoreleasepool
梵得儿SHI1 个月前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制
梵得儿SHI1 个月前
Java 反射机制深度解析:从运行时 “解剖” 类的底层逻辑
java·开发语言·反射·反射机制·private·类成员·反射的三大核心功能
小黑屋的黑小子7 个月前
【数据结构】反射、枚举以及lambda表达式
数据结构·面试·枚举·lambda表达式·反射机制
癞皮狗不赖皮8 个月前
Java安全基础-反射机制
java·反射机制·java安全基础
脸红ฅฅ*的思春期10 个月前
JAVA安全—反射机制&攻击链&类对象&成员变量方法&构造方法
反序列化·反射机制·java安全·链条构造
SchneeDuan1 年前
iOS-- Runtime
ios·objective-c·runtime·kvo·isa
依旧风轻1 年前
class_copyIvarList 之下,没有隐藏的属性
ios·objective-c·runtime·copyivarlist