- 数据结构
- 类对象与元类对象
- 消息传递
- 方法缓存
- 消息转发
- Method-Swizzling
- 动态添加方法
- 动态方法解析
数据结构
- objc_object
- objc_class
- isa指针
- method_t
objc_object(id = objc_object)
- isa_t
- 关于isa操作相关
- 弱引用相关
- 关联对象相关
- 内存管理相关
objc_class
isa指针
- 共用体isa_t
- isa指向
- 关于对象,其指向类对象
- 关于类对象,其指向元类对象
cache_t
- 用于快速查找方法执行函数
- 是可增量扩展的哈希表结构
- 是局部性原理的最佳应用
class_data_bits_t
- class_data_bits_t主要是对class_rw_t的封装
- class_rw_t代表了类相关的读写信息、对class_ro_t的封装
- class_ro_t代表了类相关的只读信息
class_rw_t
class_ro_t
method_t
Type Encodings
- const char* types
- 更多关于Type Encodings developer.apple.com
整体数据结构
对象、类对象、元类对象
-
类对象存储实例方法列表等信息
-
元类对象存储类方法列表
笔试题
#import "Mobile.h"
@interface Phone : Mobile
@end
@implementation Phone
- (id)init
{
self = [super init];
if(self){
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([super class]));
}
return self;
}
// 输出结果一致,均为Phone。
消息传递
- void objc_msgSend(void /id self,SEL op,.../)
- void objc_msgSendSuper(void /*struct objc_super super,SEL op,.../)
struct objc_super {
Specifies an instance of a class.
_unsafe\_unretained id reciver;(reciver->self)
}
缓存查找
-
例:给定值是SEL,目标值是对应bucket_t中的IMP
-
f(key) = key & mask
-
当前类中查找
- 对于已排序好的列表,采用二分查找算法查找方法对应函数执行
- 对于没有排序的列表,采用一般遍历查找方法对应函数执行
父类逐级查找
消息转发
可以进行代码演示进行验证。
Method-Swizzling
代码演示
- 导入runtime的头文件 #import <objc/runtime.h>
- 获取方法
+ (void)load
{
Method test = class_getInstanceMethod(self,@selector(test));
Method otherTest = class_getInstanceMethod(self,@selector(otherTest));
交换方法
method_exchangeImplementations(test,otherTest);
}
- 实际使用如:
- 交换ViewController中的viewDidAppear等方法,添加相应的操作,如统计等。
动态添加方法
- performSelector: 编译时没有方法,运行时才有的方法。主要考察runtime动态添加方法。
- 动态添加test方法的实现
- void testImp (void){}
- class_addMethod(self,@selector(test),testImp,"v@:");
动态方法解析
@dynamic :
- 标记为@dynamic则set,get方法,运行时决定
- 动态运行时语言将函数决议推迟到运行时。
- 编译时语言在编译期进行函数决议。
Runtime实战
- [objc foo]和objc_msgSend()函数之间有什么关系?
- runtime如何通过Selector找到对应的IMP地址的?(先找缓存,当前类方法,找继承类)
- 能否向编译后的类中增加实例变量?(内存布局完成后,不能增加,ro不可更改)