03进阶之路-Runtime
1. 类Runtime数据结构
学习链接
- objc_class (类对象)
struct objc_class {
Class _Nonnull isaOBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_classOBJC2_UNAVAILABLE;
const char * _Nonnull nameOBJC2_UNAVAILABLE;
long versionOBJC2_UNAVAILABLE;
long infoOBJC2_UNAVAILABLE;
long instance_sizeOBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivarsOBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodListsOBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cacheOBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocolsOBJC2_UNAVAILABLE;
#endif} OBJC2_UNAVAILABLE;
这是已经失效的类对象的结构,但是也反映了类对象基本数据结构
真实的类对象的结构是
objc_class |
---|
isa_t isa |
Class superClass |
cache_t cache |
class_data_bits_t bits |
- class_data_bits_t 结构
其中只含有一个 64 位的 bits 用于存储与类有关的信息:
64位数据包含了 四个信息
第 [3, 47] 位 :class_rw_t * 指针只存于第 [3, 47] 位
第0位: isSwift():FAST_IS_SWIFT 用于判断 Swift 类
第1位:hasDefaultRR():FAST_HAS_DEFAULT_RR 当前类或者父类含有默认的retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 方法
第2位:requiresRawIsa():FAST_REQUIRES_RAW_ISA 当前类的实例需要 raw isa
- class_rw_t 和 class_ro_t 结构
文章图片
image - method_t
struct method_t {
SEL name;
const char *types;
IMP imp;
};
- Type Encodings 类型编码
- 类对象
继承自objc_class 存储实例方法,变量,属性列表,协议列表
- 元类对象
根元类继承根类对象 存储对象方法 看懂下图就明白了
文章图片
image
- 【03进阶之路-Runtime】消息传递
实例类调用实例方法通过isa指针找到他的类对象,在类对象的缓存列表里面查找,没有找到在自己的实例方法列表里面查找,没有在沿着父类的指针查找下去,根类对象都没有,进入消息转发流程
调用类方法:类对象通过isa指针找到元类对象,在元类对象的缓存列表里面查找,没有找到通过父类指针继续查找,根元类没有,就到根类对象的实例方法查找(注意根元类的superclass是根类对象),有就调用,没有进行消息转发
计算机局部性原理的应用
hashMap实现,以方法名为key,在里面查找
4. 消息转发
学习链接
如果一个方法没有实现,消息传递机制结束之后就会进入消息转发流程,给我们三次拯救的机会
首先调用 +(BOOL)resolveInstanceMethod:(SEL)sel或者+ (BOOL)resolveClassMethod:(SEL)sel
给我们一次动态实现的机会,如果返回yes 会重新走一遍消息传递的流程第二次调用-(id)forwardingTargetForSelector:(SEL)aSelector
给我们一次转发给其他对象,如果返回一个非nil.消息将会转发给该对象第三次调用- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector方法来获取这个选择子的方法签名.然后在- (void)forwardInvocation:(NSInvocation *)anInvocation处理
文章图片
image 5. 黑魔法Method-Swizzling
就是imp指针混写技术.可以改变系统方法.hook系统方法,注意在load方法里面替换.
6. 动态添加方法
oid speak(id self, SEL _cmd){
NSLog(@"Now I can speak.");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {NSLog(@"resolveInstanceMethod:%@", NSStringFromSelector(sel));
if (sel == @selector(speak)) {
class_addMethod([self class], sel, (IMP)speak, "V@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
7. 动态方法解析
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"forwardInvocation: %@", NSStringFromSelector([anInvocation selector]));
if ([anInvocation selector] == @selector(code)) {
Monkey *monkey = [[Monkey alloc] init];
[anInvocation invokeWithTarget:monkey];
}
}- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSLog(@"method signature for selector: %@", NSStringFromSelector(aSelector));
if (aSelector == @selector(code)) {
return [NSMethodSignature signatureWithObjCTypes:"V@:@"];
}
return [super methodSignatureForSelector:aSelector];
}
推荐阅读
- 定投,开启个人品牌之路
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- 财富自由之路
- 《通往财富自由之路》人生的终极问题到底是什么()
- 普通人进阶的三个过程-很多人都知道,但却本末倒置
- 易效能进阶课程笔记29
- 读李笑来老师的“财富自由之路”7/365
- 读《财富自由之路》有感
- 99_读|99_读 被讨厌的勇气_岸见一郎
- 复盘学习《通往财富自由之路》专栏——“我们重新理解了付费”