学习MJ的视频课程,整理总结知识点–Runtime API
本文主要简单介绍Runtime常用的一些API,相关的API包括类、成员变量、属性、方法等。另,文章前面已介绍不少Runtime的API,这里不再重复
中间代码
先补充一些知识点,关于查看OC代码转换后的底层实现的手段
- 通过clang转换为cpp文件
用于查看OC代码转化的C、C++代码,导出的一般是编译阶段的代码,和运行时真实调用的底层代码可能会有细小的差异,可以用于参考,但是代码逻辑基本上一致,可以用于分析OC的底层实现。
1 | objc_msgSendSuper({self, class_getSuperclass(objc_getClass("MJPerson"))}, @selector(forwardInvocation:), anInvocation); |
- Xcode断点Debug选择
Always Show Disassembly
查看运行阶段的汇编代码
1 | 0x100000e8e <+62>: movq 0x29b(%rip), %rdx ; "forwardInvocation:" |
- Xcode选择
Product
-> Assembly xx文件,转成汇编4、clang导出中间代码1
2
3
4
5
6
7
8
9
10.loc 2 29 5 ## Interview01-super/MJPerson.m:29:5
movq %rdx, -40(%rbp)
movq L_OBJC_CLASSLIST_SUP_REFS_$_(%rip), %rdx
movq %rdx, -32(%rbp)
movq L_OBJC_SELECTOR_REFERENCES_.2(%rip), %rdx
leaq -40(%rbp), %rdi
movq %rsi, -64(%rbp) ## 8-byte Spill
movq %rdx, %rsi
movq -64(%rbp), %rdx ## 8-byte Reload
callq _objc_msgSendSuper2
苹果是通过LLVM把OC代码转成最终执行的机器码,大致过程OC -> 中间代码 -> 机器码
LLVM跨平台的,汇编、机器码是区分平台的
1 | define internal void @"\01-[MJPerson forwardInvocation:]"(%0*, i8*, %1*) #1 { |
Objective-C在变为机器代码之前,会被LLVM编译器转换为中间代码(Intermediate Representation)
可以使用以下命令行指令生成中间代码c
lang -emit-llvm -S main.m
语法简介
@ - 全局变量
% - 局部变量
alloca - 在当前执行的函数的堆栈帧中分配内存,当该函数返回到其调用者时,将自动释放内存
i32 - 32位4字节的整数
align - 对齐
load - 读出,
store 写入
icmp - 两个整数值比较,返回布尔值
br - 选择分支,根据条件来转向
label,不根据条件跳转的话类似
gotolabel - 代码标签
call - 调用函数
具体可以参考官方文档:https://llvm.org/docs/LangRef.html
Runtime API - 类
动态创建一个类,添加属性,添加方法,注册类
1 | MJPerson *person = [[MJPerson alloc] init]; |
Runtime API - 成员变量
应用-找textfiled
Ivar *ivars
C语言取数据时数组和指针没什么区别
Ivar ivar = *(ivars + i)
Runtime实现字典转模型
ivarlist
Runtime API – 方法
拦截所有按钮的点击事件
方法交换,交换的是class_rw_t->methods->method_lsit(method_t)->imp
1 | @implementation UIControl (Extension) |
NSMutableArray数据插空处理
类簇:NSString、NSArray、NSDictionary,真实类型是其他类型
1 | @implementation NSMutableArray (Extension) |
字典
1 | @implementation NSMutableDictionary (Extension) |
fishhook
总结
什么是Runtime?平时项目中有用过么?
OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行OC的动态性就是由Runtime来支撑和实现的,Runtime是一套C语言的API,封装了很多动态性相关的函数平时编写的OC代码,底层都是转换成了Runtime API进行调用
应用
关联对象给分类添加属性
获取遍历类的成员变量,修改私有变量
字典转模型、自动归档解档
交换方法实现(交换系统的方法,导航栏样式)
利用消息转发机制解决方法找不到的异常问题
参考和源码
源码: