Runtime内容如下:
- 数据结构
- 类对象与元类对象
- 消息传递
- 方法缓存
- 消息转发
- Method-Swizzling
- 动态添加方法
- 动态方法解析
Runtime.png
1.数据结构
- objc_object
- objc_class
- isa指针
- method_t
-
objc_object
objc_object.png
id = objc_object
-
objc_class
objc_class.png
- class 等同于 objc_class
- objc_class继承于objc_object
- objc_class 包含 superClass,cache,bits.
- isa指针
isa指针.png
- 指针型isa
isa的值代表Class的地址
- 非指针型isa
isa的值得部分代表Class的地址
思考-面试题:isa的含义?
对象->类对象.png
isa指向:
- 关于对象,其指向类对象
类对象->元类对象.png
关于元类,其指向元类对象
- cache_t
- 用于快速查找方法执行函数
- 增量扩展的哈希表结构
- 局部性原理的应用
cache_t.png
- 理解一个数组来实现
- 数组每一个对象都是bucket_t结构体封装
- bucket_t两个成员变量key ,IMP
- key对应OC selector
- IMP理解为无类型的函数指针
- class_data_bits_t
- 对class_rw_t的封装
- class_rw_t代表了类相关的读写信息,对calss_ro_t的封装
- class_ro_t代表了类相关的只读信息
class_rw_t.png
- class_rw_t
- 包括class_ro_t,protocols,properties,methods
- protocols,properties,methods,是一个二维数组
class_ro_t.png
- class_ro_t
- 包括name,ivars,properties,protocols,methodList
- ivars,,properties,protocols,methodList对应一维数组
- method_t
- 函数四要素
名称
返回值
参数
函数体
- method_t
- SEL name; //函数名
- const char* types; 返回值类型及参数类型
- IMP imp; //无返回值的函数体
-(void)method; == v@:
v->void
@->id
:->SEL
-
整体数据结构
Runtime数据结构.png
2.类对象与元类对象
类对象与元类对象.png
- 类对象存储实例方法列表等信息
- 元类对象存储类方法列表等信息
思考-面试题
#import "Food.h"
@interface Beef : Food
@end
---------------------------------
@implementation Beef
-(id)init{
self = [super init];
if(self){
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([super class]));
}
return self;
}
3.消息传递
void objc_msgSend
objc_msgSend.png
void objc_msgSendSuper
objc_msgSendSuper.png
消息传递过程
消息传递过程.png
缓存查找
缓存查找.png
当前类中查找
对于已排序好的列表,采用二分查找算法查找方法对应执行函数
对于没有排序的列表,采用一般遍历查找方法对应执行函数
父类逐级查找
父类逐级查找.png
4.消息转发
消息转发流程.png
5.Method-Swizzling
Method-Swizzling.png
方法交换
6.动态添加方法
void test1 (void)
{
NSLog(@"test1");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(test)) {
NSLog(@"resolveInstanceMethod:");
// 动态添加test方法的实现
class_addMethod(self, @selector(test), test1, "v@:");
return YES;
}
else{
// 返回父类的默认调用
return [super resolveInstanceMethod:sel];
}
}
7.动态方法解析
动态运行时语言将函数决议推迟到运行时
8.面试
- [obj eat] 和objc_msgSend()函数之间有什么关系?
- runtime如何通过Selector找到对应的IMP地址的?
- 能否在编译后的类中增加实例变量?
QQ交流群: 796142709








网友评论