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 结构

    03进阶之路-Runtime
    文章图片
    image
  • method_t
struct method_t { SEL name; const char *types; IMP imp; };

  • Type Encodings 类型编码
2. 类对象和元类对象和消息传递
  • 类对象
    继承自objc_class 存储实例方法,变量,属性列表,协议列表

  • 元类对象
    根元类继承根类对象 存储对象方法 看懂下图就明白了

03进阶之路-Runtime
文章图片
image
  • 【03进阶之路-Runtime】消息传递
    实例类调用实例方法通过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处理

03进阶之路-Runtime
文章图片
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]; }

    推荐阅读