动态性
OC运行时
Objective-C Runtime 是 Objective-C 语言的核心部分,它是一套 C 语言库,负责实现动态特性,如动态类型检查、动态消息传递、动态方法解析等。Objective-C 作为一种动态语言,在编译时并不会将所有信息都确定下来,而是通过 Runtime 来在运行时处理对象和消息的调用。
在 Objective-C 中,方法调用实际上是通过向对象发送消息来实现的。Runtime 会在运行时决定哪个方法对应于这个消息,并调用相应的方法。Objective-C 允许在运行时检查对象的类型,并根据对象的实际类型执行操作。这种灵活性使得代码更具适应性和扩展性。当一个对象接收到无法处理的消息时,Runtime 提供了钩子方法,可以在运行时添加相应的实现,动态解析该方法。通过 Runtime,你可以动态地给类添加关联对象,使得在不修改类源码的情况下为对象添加额外的属性。
Objective-C Runtime 的常用运用有哪些呢?
方法交换 (Method Swizzling)
方法交换是指在运行时交换两个方法的实现。这种技术通常用于 AOP(面向切面编程),例如拦截系统方法以插入自定义逻辑。
1 | Method originalMethod = class_getInstanceMethod([self class], @selector(viewWillAppear:)); |
动态添加方法
你可以使用 class_addMethod 动态给类添加方法。这在需要扩展类功能但无法修改类源码时非常有用。
1 | void dynamicMethodIMP(id self, SEL _cmd) { |
获取类信息
通过 Runtime,可以获取类的各种信息,如属性列表、方法列表、协议列表等,这些信息有助于在运行时对类进行动态操作。
1 | unsigned int count; |
关联对象
Runtime 允许为对象动态关联数据。这在扩展现有类时非常有用,尤其是在不想子类化的情况下。
1 | const char *key = "associatedObject"; |
消息转发 (Message Forwarding)
1 | - (void)forwardInvocation:(NSInvocation *)anInvocation { |
Swift运行时
Mirror 应用场景
Mirror反射API主要用于以下几个方面:
- 动态获取对象的类型信息:通过Mirror反射API,可以动态获取对象的类型信息,包括类型名称、属性信息等。
- 遍历对象的属性:通过Mirror反射API,可以遍历对象的属性,获取属性名称和值等信息。
- 实现自定义调试输出:通过Mirror反射API,可以实现自定义的调试输出,将对象的属性信息格式化输出到控制台或日志中。
Mirror反射API在Swift中具有广泛的应用场景,特别是在调试和日志输出等方面。通过Mirror反射API,可以方便地获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码。
Mirror 优缺点
Mirror反射API的优点主要包括以下几个方面:
- 动态获取类型信息:Mirror反射API可以动态获取对象的类型信息,包括类型名称、属性信息等。
- 遍历对象属性:Mirror反射API可以遍历对象的属性,获取属性名称和值等信息。
- 实现自定义调试输出:Mirror反射API可以实现自定义的调试输出,将对象的属性信息格式化输出到控制台或日志中。
Mirror反射API的缺点主要包括以下几个方面:
- 性能开销:Mirror反射API会带来一定的性能开销,特别是在遍历对象属性时,可能会影响程序的性能。
- 限制功能:Mirror反射API的功能相对有限,只能获取对象的类型信息和属性信息,无法实现更复杂的操作。
Mirror 工作原理
Mirror反射API的工作原理主要包括以下几个步骤:
- 获取对象的类型信息:Mirror反射API通过Swift的反射机制获取对象的类型信息,包括类型名称、属性信息等。
- 创建Mirror实例:根据类型信息创建Mirror实例,包括Mirror的基本信息和属性信息。
- 遍历对象属性:通过Mirror实例遍历对象的属性,获取属性名称和值等信息。
- 输出属性信息:将属性信息格式化输出到控制台或日志中,实现自定义的调试输出。
Mirror反射API的工作原理主要依赖于Swift的反射机制,通过反射机制获取对象的类型信息,然后根据类型信息创建Mirror实例。Mirror反射API在Swift中具有广泛的应用场景,特别是在调试和日志输出等方面。
Mirror反射API由Swift实现的ReflectionMirror.swift和C++实现的ReflectionMirror.mm两部分组成。Swift部分主要负责Mirror类的定义和基本功能实现,C++部分则负责底层的反射数据获取和处理。解释两者之间通过@_silgen_name修饰符进行函数映射的通信机制。
Mirror结构体的定义及其初始化方法,包括处理CustomReflectable类型和非CustomReflectable类型。internalReflecting方法包括如何获取subject的真正类型、属性大小、遍历属性并存储到字典中,以及处理父类Mirror的逻辑。_getNormalizedType方法获取传入的subject的真正类型,并调用C++中的swift_reflectionMirror_normalizedType -> Call方法。
ReflectionMirrorImpl的主要种类,如TupleImpl、StructImpl、EnumImpl、ClassImpl、MetatypeImpl、OpaqueImpl等。StructImpl通过metadata获取属性个数、属性名称和值,以及通过指针计算属性存储的地址。
Mirror 代码示例
1 | class Movie: NSObject { |
上述代码示例中,定义了一个Movie类,并创建了一个Movie实例movieInstance。通过Mirror反射API,遍历了movieInstance对象的属性,并输出了属性名称和值。
通过Mirror反射API,可以方便地获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码。
Mirror 与 Runtime
Mirror反射API与Runtime机制在Swift中都是用于处理对象的类型信息和属性信息的技术。Mirror反射API主要用于获取对象的类型信息和属性信息,而Runtime机制主要用于处理对象的生命周期和内存管理。
Mirror反射API通过Swift的反射机制获取对象的类型信息,包括类型名称、属性信息等。通过Mirror反射API,可以动态获取对象的类型信息,遍历对象的属性等操作。
Runtime机制是Swift的底层机制,用于处理对象的生命周期和内存管理。Runtime机制主要包括对象的创建、销毁、内存分配和释放等操作,以及对象的方法调用、属性访问等操作。
Mirror反射API和Runtime机制在Swift中都是用于处理对象的类型信息和属性信息的技有,但功能和应用场景有所不同。Mirror反射API主要用于获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码;Runtime机制主要用于处理对象的生命周期和内存管理,保证程序的稳定性和性能。
Mirror 与 KVC
Mirror反射API与KVC(Key-Value Coding)在Swift中都是用于处理对象的属性信息的技术。Mirror反射API主要用于获取对象的类型信息和属性信息,而KVC主要用于访问对象的属性值。
Mirror反射API通过Swift的反射机制获取对象的类型信息,包括类型名称、属性信息等。通过Mirror反射API,可以动态获取对象的类型信息,遍历对象的属性等操作。
KVC是一种通过字符串键访问对象属性的技术,可以动态访问对象的属性值。KVC主要包括setValue:forKey:和valueForKey:等方法,用于设置和获取对象的属性值。
Mirror反射API和KVC在Swift中都是用于处理对象的属性信息的技术,但功能和应用场景有所不同。Mirror反射API主要用于获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码;KVC主要用于访问对象的属性值,实现动态属性访问和赋值等操作。
Mirror 与 Codable
Mirror反射API与Codable协议在Swift中都是用于处理对象的属性信息的技术。Mirror反射API主要用于获取对象的类型信息和属性信息,而Codable协议主要用于对象的编码和解码。
Mirror反射API通过Swift的反射机制获取对象的类型信息,包括类型名称、属性信息等。通过Mirror反射API,可以动态获取对象的类型信息,遍历对象的属性等操作。
Codable协议是Swift的标准库协议,用于对象的编码和解码。Codable协议主要包括Encodable和Decodable两个子协议,用于对象的序列化和反序列化操作。
Mirror反射API和Codable协议在Swift中都是用于处理对象的属性信息的技术,但功能和应用场景有所不同。Mirror反射API主要用于获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码;Codable协议主要用于对象的编码和解码,实现对象的序列化和反序列化操作。
Mirror 与 PropertyWrapper
Mirror反射API与PropertyWrapper属性包装器在Swift中都是用于处理对象的属性信息的技术。Mirror反射API主要用于获取对象的类型信息和属性信息,而PropertyWrapper属性包装器主要用于属性的封装和访问控制。
Mirror反射API通过Swift的反射机制获取对象的类型信息,包括类型名称、属性信息等。通过Mirror反射API,可以动态获取对象的类型信息,遍历对象的属性等操作。
PropertyWrapper属性包装器是Swift 5.1引入的新特性,用于属性的封装和访问控制。PropertyWrapper属性包装器主要包括@propertyWrapper和wrappedValue等属性,用于属性的封装和访问控制。
Mirror反射API和PropertyWrapper属性包装器在Swift中都是用于处理对象的属性信息的技术,但功能和应用场景有所不同。Mirror反射API主要用于获取对象的类型信息和属性信息,帮助开发者更好地理解和调试代码;PropertyWrapper属性包装器主要用于属性的封装和访问控制,实现属性的封装和访问控制等操作。
动态库注入技术
TrollFools
TrollFools 是一个开源的 iOS 工具,专为 TrollStore 环境设计,用于向 iOS 设备上的应用程序注入和移除插件。
TrollStore 允许用户直接安装 .ipa 文件。这是 TrollFools 能够工作的基础环境。
TrollFools 通过将动态库(dylib)注入到目标应用程序中,来实现对应用程序功能的增强或修改。这些动态库包含了额外的代码,用于在应用程序运行时执行特定的功能。在注入过程中,TrollFools 可能会修改应用程序的二进制文件,以加载并链接这些动态库。这通常涉及到对应用程序的 Mach-O 格式的修改,以确保动态库能够被正确加载和执行。
TrollFools 使用 SwiftUI 编写,这为用户提供了一个现代化的、易于使用的开发环境。开发者可以利用 SwiftUI 的强大功能来创建直观且功能丰富的界面,以进一步扩展 TrollFools 的功能。
由于 optool 存在一些问题,TrollFools 需要编译一个静态链接的 install_name_tool 或 llvm-install-name-tool 以在 iOS 上使用,从而实现更小的包大小。这有助于减少应用占用的存储空间,提高设备的整体性能。