底层探索

作者: 撒花小仙女_卡卡 | 来源:发表于2019-07-02 16:33 被阅读0次

    开启汇编的步骤:Debug->Debug Workflow->Always Show Disassembly
    objc_msgSend
    打断点然后同时点击control和箭头所指进入


    https://opensource.apple.com
    SEL->IMP
    CacheLookup:1、有缓存机制
    2、CacheHit找到缓存
    3、CheckMiss->MethodTableLookup
    4、add
    对象->结构体->class
    class:1、方法列表
    2、属性列表
    3、协议列表
    ---------------------------------------以上快速查找---------------------------------
    IMP_class_lookupMethodAndLoadCache3(id obj,SEL sel,Class cls){
      return lookUpImpOrForward(cls, sel,obj,YES/*initialize*/,NO/*cache*/,YES/*resolver*/);
    }
    

    慢速查找:cls类对象、实例对象、元类对象
    ⚠️实例方法存在类对象里面
    ⚠️类方法存在元类里面
    ⚠️方法查找首先在自己的类的方法列表里查找,有的话直接log_and_fill_cache,没有的话去父类中查找,如果父类中有,也要log_and_fill_cache,一直找到NSObject

    unsigned attempts = unreasonableClassCount();
    for (Class curClass = cls ->superclass;
           curClass != nil;
           curClass = curClass ->superclass)
    {
             if(--attempts == 0){
                _objc_fatal("Memory corruption in class list.")
              }
             imp = cache_getImp(curClass, sel);
             if(imp){
                 if(imp != (IMP)_objc_msgForward_impcache){
                    log_and_fill_cache(cls,imp,sel,inst,curclass);
                    goto done;
                 }
                 else{
                     break;
                 }
             }
             Method meth = getMethodNoSuper_nolock(curClass,sel);
             if(meth){
               log_and_fill_cache(cls,meth->imp,sel,inst, curClass);
               imp = meth->imp;
               goto done;
             }
             if(resolver && !triedResolver){
             runtimeLock.unlock();
             _class_resolveMethod(cls,sel,inst);
             runtimeLock.lock();
             triedResolver = YES;
             goto retry;
             }
    }
    

    isa走位图

    屏幕快照 2019-07-01 下午4.57.03.png

    动态方法解析
    ⚠️消息转发流程如下图所示:
    ⚠️⚠️⚠️动态方法解析只解析一次

    屏幕快照 2019-07-02 上午10.30.03.png
    //类方法动态解析
    void _class_resolveMethod(Class cls,SEL sel,id inst)
    {
        if(! cls -> isMetaClass()){
           _class_resolveInstanceMethod(cls,sel,inst);
        }
        else{
        _class_resolveClassMethod(cls,sel,inst);
        if(!lookUpImpOrNil(cls,sel,inst
                           NO/*initialize*/,YES/*cache*/,NO/*resolver*/))
        }
    }
    
    //实例方法动态解析
    static void _class_resolveInstanceMethod(Class cls,SEL sel,id inst)
    {
      if(! lookUpImpOrNil(cls->ISA(),SEL_resolveInstanceMethod,cls,
                                NO/*initialize*/,YES/*cache*/,NO/*resolver*/)){
          return;
    }
      BOOL (*msg)(Class,SEL,SEL) = (typeof(msg))objc_msgSend;
      bool resolved = msg(cls,SEL_resolveInstanceMethod, sel);
      IMP imp = lookUpImpOrNil(cls,sel,inst,NO/*initialize*/,YES/*cache*/,NO/*resolver*/);
      if(resolver && PrintResolving){
         if(imp){
            _objc_inform(@"RESOLVE:method %c[%s %s] " "dynamically resolved to %p", cls - > isMetaClass()?'+':'-',cls->nameForLogginh(),sel_getName(sel),imp);
       }
      }
    }
    
    //消息转发
    -(id)forwardingTargetForSelector:(SEL)aSelector{
       NSLog(@"%s",__func__);
       return [super forwardingTargetForSelector: aSelector];
    }
    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
       //方法签名
      if(aSelector == @selector(run)){
         Method method = class_getInstanceMethod([self class],@selector(runMethod));
         const char *type = method_getTypeEncoding(method);
         return [NSMethodSignature methodSignatureForSelector: aSelector];
      }
       return [NSMethodSignature methodSignatureForSelector: aSelector];
    }
    -(void)forwardInvocation:(NSInvocation *)anInvocation{
       NSLog(@"%s-%@",__func__,NSStringFromSelector(anInvocation.selector));
       anInvocation.selector = @selector(runMethod);
       [anInvocation invoke];
    }
    

    相关文章

      网友评论

        本文标题:底层探索

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