工作生活

底层探索

2019-07-02  本文已影响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];
}
上一篇下一篇

猜你喜欢

热点阅读