Runtime 是由汇编, C, C++语言编写的,可以防方法crash,收集crash信息
OC是一门动态语言,Runtime就是提供OC运行时的API
编译时:源代码翻译成机器语言
运行时:OC代码运行起来,加载到内存
Runtime是OC语言的底层

Runtime API 列表
https://www.jianshu.com/p/845f2180722b
调用runtime 有三种方式
1. OC上层代码代码 @selector
2.NSObject API 如 isKindOfClass
3. runtime api
Runtime 运行,方法调用
_objc_msgSend使用汇编语言,效率高,能够根据未知的指针,直接跳转(C实现不了)
方法查找
汇编部分快速查找 __class_lookupMethodAndLoadCache3 之前
C C++部分慢速查找 __class_lookupMethodAndLoadCache3 之后

方法查找是二分查找, 缓存 + 方法列表(分类方法 + 本身方法,同名分类方法先查找到)
方法查找不到,进入动态方法解析

实例方法动态解析

知道会走NSObject 的 + (BOOL)resolveInstanceMethod:(SEL)sel
类方法动态解析
void _class_resolveMethod(Class cls, SEL sel, id inst)
{
if (! cls->isMetaClass()) {
// try [cls resolveInstanceMethod:sel]
_class_resolveInstanceMethod(cls, sel, inst);
}
else {
// try [nonMetaClass resolveClassMethod:sel]
// and [cls resolveInstanceMethod:sel]
_class_resolveClassMethod(cls, sel, inst);
if (!lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/))
{
_class_resolveInstanceMethod(cls, sel, inst);
}
}
}
if (!lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/))
{
_class_resolveInstanceMethod(cls, sel, inst);
}
类方法动态解析,在进行resolveClassMethod解析, 会判断一次未实现的方法得到解决没,没有的话在进行一次resolveInstanceMethod解析
无论类方法还是实例方法,都会调用
+ (BOOL)resolveInstanceMethod:(SEL)sel
在NSObject 中,避免resolveClassMethod或者resolveInstanceMethod找不到造成的死循环
+ (BOOL)resolveClassMethod:(SEL)sel {
return NO;
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
return NO;
}
类方法动态解析未解决问题,进行消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
在NSObject分类中
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"%s",__func__);
// if (aSelector == @selector(run)) {
// // 转发给我们的LGStudent 对象
// return [LGStudent new];
// }
return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if (aSelector == @selector(run)) {
// forwardingTargetForSelector 没有实现 就只能方法签名了
Methodmethod =class_getInstanceMethod(object_getClass(self), @selector(readBook));
const char *type = method_getTypeEncoding(method);
return [NSMethodSignature signatureWithObjCTypes: type];
}
return nil;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
NSLog(@"%s",__func__);
NSLog(@"------%@-----",anInvocation);
anInvocation.selector = @selector(readBook);
[anInvocationinvoke];
// NSString *sto = @"奔跑少年";
// anInvocation.target = [LGStudent class];
// [anInvocation setArgument:&sto atIndex:2];
// NSLog(@"%@",anInvocation.methodSignature);
// anInvocation.selector = @selector(run:);
// [anInvocation invoke];
}