iOS---Runtime

RunTime

runtime 是什么

  • runtime ,运行时机制,是一套底层 C 语言的 API,其为 iOS 内核的一部分。
  • runtime 会把我们的 Objc 代码全部转换成 C 语言。

Runtime 的相关知识

  1. SEL

    • 方法选择器,对方法进行包装,然后找到方法对应的实现。
    • 其实它就是个映射到方法的 C 字符串
    • 其结构是typedef struct objc_selector *SEL;
    • 可以用 Objective-C 编译器命令 @selector() 或者 Runtime 系统的 sel_registerName 函数来获得一个 SEL 类型的方法选择器
  2. id

    • id 是一个结构体指针类型,它可以指向 Objective-C 中的任何对象。
    • 其结构是 struct objc_object { Class isa OBJC_ISA_AVAILABILITY;}
    • 其中 isa 指针是指向对象的类
  3. Class

其结构是

   struct objc_class {
   Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
   Class super_class   OBJC2_UNAVAILABLE; //指向其超类。
   const char *name   OBJC2_UNAVAILABLE; //类名
   long version     OBJC2_UNAVAILABLE; //类的版本信息
   long info     OBJC2_UNAVAILABLE; //类的详情
   long instance_size   OBJC2_UNAVAILABLE; //该类的实例对象的大小
   struct objc_ivar_list *ivars  OBJC2_UNAVAILABLE;  //成员列表
   struct objc_method_list **methodLists  OBJC2_UNAVAILABLE;  //方法列表
   struct objc_cache *cache    OBJC2_UNAVAILABLE;  //缓存
   struct objc_protocol_list *protocols   OBJC2_UNAVAILABLE;   //协议列表
#endif
} OBJC2_UNAVAILABLE;
  1. Method
    • method_types,存放方法的参数类型和返回值类型
    • IMP 指向的是方法的实现,本质是一个函数指针
typedef struct objc_method *Method;
struct objc_method
{
    SEL method_name   ;
    char *method_types  ;
    IMP method_imp   ;
}

一个对象方法的调用的过程

  1. runtime 把我们调用的方法转化为 objc_msgSend,然后把方法的调用者和方法选择器当作参数传递过去。
  2. 通过调用者的 isa 指针,找到对应的类。
  3. 先看看当前类的 cache 中有没有该方法的调用记录,有就指直接加载,通过方法的 IMP 指针找到方法对应的实现。
  4. 如果 cache 没有,就在 methodList 找该方法。
  5. 如果该类中找不到对应的方法,就往父类找,直到 NSObject 这个类。
  6. 到 NSObject 还没有找到该类,就会进入动态方法解析。

消息转发过程

调用一个不存在的方法,程序就会 crash,在程序进入 crash 之前,会有一个消息转发的过程,如果方法还是没有被处理,程序才会 crash。

  1. 进入 resolveInstanceMethod:resolveClassMethod: 方法---动态方法解析,如果这两个方法返回的是 nil,进入下一步。
  2. 进入 forwardingTargetForSelector: 方法---对象重定向,用于指定对象来响应这个 SEL,若返回的是 self 或者是 nil ,则进入下一步消息转发。
  3. 我们首先要通过 methodSignatureForSelector: 来指定方法签名,若返回 nil,表示不处理,不会进入消息转发机制;若返回方法签名,则会进入下一步。
  4. methodSignatureForSelector: 方法返回方法签名后,就会调用 forwardInvocation: 方法---消息转发,我们可以通过 anInvocation 对象做很多处理,比如修改实现方法,修改响应对象等。


动态方法解析

+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP)
dynamicMethodIMP, "v@:");
          return YES;
}
    return [super resolveInstanceMethod:aSEL];
}

- (void)dynamicMethodIMP{
     do something;
}

说明一下
class_addMethod(Class cls, SEL name, IMP imp, const char *types) 中的参数

  • Class cls:类,哪个类去调用
  • SEL name:方法选择器
  • IMP imp:指向方法实现的指针
  • const char *types:表示返回值和参数,例如"v@:"代表"返回值是 void,没有参数";"i@:@"代表"返回值是 int,参数类型为 id"。


对象重定向

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if(aSelector == @selector(mysteriousMethod:)){
        return alternateObject;
    }
    return [super forwardingTargetForSelector:aSelector];
}


消息转发

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([someOtherObject respondsToSelector:
            [anInvocation selector]])
        [anInvocation invokeWithTarget:someOtherObject];
    else
        [super forwardInvocation:anInvocation];
}
  • 在 forwardInvocation: 消息发送前,Runtime 系统会向对象发送methodSignatureForSelector: 消息,并取到返回的方法签名用于生成 NSInvocation 对象,所以我们也需要重写 methodSignatureForSelector: 返回签名。


方法中隐藏的参数

  • 当 objc_msgSend 找到对应方法的实现时,会把消息中的所有参数传给方法的实现,还加上两个隐藏的参数:
    1. self 当前方法的对象指针
    2. SEl 方法选择器

当我们调用[super method]时的过程

  1. 构造 objc_super 结构体 struct objc_super { id receiver; Class super_class; }
    • 其中 receiver 仍然是 self 本身
    • super_class 父类
  2. 因为结构体有 super_class 这个成员变量,系统就会调用 objc_msgSendSuper 这个方法,然后把将这个结构体和方法选择器都传递过去。
  3. 从 objc_super 结构体指向的 superClass 的方法列表开始找 setName 的 selector,找到后再以 objc_super->receiver 去调用这个 selector

即还是 self 去调用父类的方法

推荐一篇关于对象关联的贴子,写得很好
http://www.jianshu.com/p/79479a09a8c0#%E5%85%B3%E8%81%94%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BA%94%E7%94%A8

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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,690评论 0 9
  • 本文转载自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex阅读 751评论 0 1
  • runtime 和 runloop 作为一个程序员进阶是必须的,也是非常重要的, 在面试过程中是经常会被问到的, ...
    SOI阅读 21,791评论 3 63
  • 技 术 文 章 / 超 人 Runtime(运行时机制)概念 Object-C 是面向对象的语言,C是面向结构也就...
    树下敲代码的超人阅读 1,004评论 0 16
  • 简介(http://www.cnblogs.com/ioshe/p/5489086.html) Runtime 又...
    清风沐沐阅读 505评论 0 0