1. 类Runtime数据结构
学习链接
- objc_class (类对象)
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_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 结构
method_t
struct method_t {
SEL name;
const char *types;
IMP imp;
};
- Type Encodings 类型编码
2. 类对象和元类对象和消息传递
-
类对象
继承自objc_class 存储实例方法,变量,属性列表,协议列表
-
元类对象
根元类继承根类对象 存储对象方法 看懂下图就明白了
-
消息传递
实例类调用实例方法通过isa指针找到他的类对象,在类对象的缓存列表里面查找,没有找到在自己的实例方法列表里面查找,没有在沿着父类的指针查找下去,根类对象都没有,进入消息转发流程
调用类方法:类对象通过isa指针找到元类对象,在元类对象的缓存列表里面查找,没有找到通过父类指针继续查找,根元类没有,就到根类对象的实例方法查找(注意根元类的superclass是根类对象),有就调用,没有进行消息转发
3. 方法缓存查找
计算机局部性原理的应用
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处理
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];
}