美文网首页
20期_iOS_方法查找流程分析

20期_iOS_方法查找流程分析

作者: 萧修 | 来源:发表于2023-08-21 01:55 被阅读0次

    从objc_msgsend入手有两个参数id(消息接受者)、sel(方法编号)

    runtime调用

    • Objective-C: Selector调用
    • NSObject:performSelector调用
    • runtime的api调用

    一些总结

    • 父类对象方法要从父类方法列表进行查找
    • 父类类方法要去父类元类方法列表查找
    • 父类的类方法调用主体是Class
    • super调用父类方法,是告诉系统从父类方法列表查找,但调用主体仍旧是self

    快速查找就是自从cache_t中查找缓存,缓存名字查找结束。否则开始做慢速查找前的准备工作,并跳转到慢速查找流程

    慢速查找

    关键函数

    IMP lookUpImpOrForward(id inst, SEL sel, Class cls, int behavior)
    {
        
        /if (curClass->cache.isConstantOptimizedCache(/* strict */true)) {
    #if CONFIG_USE_PREOPT_CACHES
                imp = cache_getImp(curClass, sel);
                if (imp) goto done_unlock;
                curClass = curClass->cache.preoptFallbackClass();
    #endif
            } else {
                // curClass method list.
                //通过本方法的方法列表查找,如果找到meth直接返回
                method_t *meth = getMethodNoSuper_nolock(curClass, sel);
                if (meth) {
                    imp = meth->imp(false);
                    goto done;
                }
                
    
                //递归查找父类方法
                if (slowpath((curClass = curClass->getSuperclass()) == nil)) {
                    // No implementation found, and method resolver didn't help.
                    // Use forwarding.
                    imp = forward_imp;
                    break;
                }
            }
    }
    

    log_and_fill_cache填充缓存

    慢速查找是从本类查找到父类,再到NSObject的方法查找,先找本类方法列表,找到填充缓存,找不到去父类缓存和方法列表,找到缓存,找不到去转发

    面试题:子类可以调用类方法实现NSObject的对象方法
    验证

    @implementation NSObject (GX)
    //分类声明
    - (void)instanceMethod{
        NSLog(@"%s--我是对象方法",__func__);
    }
    
    @end
    
    调用
    //验证子类类方法调用 nsob对象方法
    [GGXPerson instanceMethod];
    

    类方法调用,GGXPerson的类方法存在其元类,最后找到根元类方法调用,如果没有对应类方法实现,根元类supper指向NSObject,去查找NSObkect方法列表。

    相关文章

      网友评论

          本文标题:20期_iOS_方法查找流程分析

          本文链接:https://www.haomeiwen.com/subject/qdunpdtx.html