OC Runtime

Runtime 是由汇编, C, C++语言编写的,可以防方法crash,收集crash信息

OC是一门动态语言,Runtime就是提供OC运行时的API

编译时:源代码翻译成机器语言

运行时:OC代码运行起来,加载到内存

Runtime是OC语言的底层

Runtime层次

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];

}  

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容