底层探索

开启汇编的步骤: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];
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358

推荐阅读更多精彩内容

  • 参考官方文档 KVC概述 键值编码是一种由NSKeyValueCoding非正式协议启用的机制,对象采用该机制提供...
    淡定的笨鸟阅读 767评论 0 8
  • KVO是Objective-C中的键值监听策略,本篇能学习到以下知识点1、KVO的使用方法大全2、KVO的底层如何...
    淡定的笨鸟阅读 1,009评论 0 3
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,107评论 1 32
  • 序言 前几天公交车上看了一篇百度大神的关于 KVO 探索的博客。我实地验证了一下子,也遇到了好多问题,一番各种查阅...
    黃小梦阅读 1,186评论 8 29
  • 曾经的秋,寄托着我各种思绪,柔软的让我说不出话来。 晨跑,眼睛掠过水杉,惊奇地发现像金字塔模样的水杉,外一圈像是涂...
    卿若安阅读 200评论 2 2