runtime

作者: sweetpf | 来源:发表于2017-08-30 15:08 被阅读13次

    作为iOS开发者,runtime特性是必须了解的重点加分项。这并不是说你可以说出消息机制,运行时消息重定向,或者利用runtime特性实现交换方法等,而是更应该深入了解其原理,"知其然且知其所以然"才能不断成长。
    Object-C是面相运行时的语言(runtime oriented language),它将编译和链接时要执行的逻辑延迟到运行时来处理。相对静态语言,我们的代码更具灵活性,在苹果封闭链中这个特性也能帮助我们进行线上修复,例如业界鼎鼎大名的JSPatch(虽然现在苹果为了安全性,一封邮件“封杀”JSPatch)。那本篇文章先从runtime功能入手,让你体会runtime的强大,再介绍其原理。在此之前,先了解下基础知识。

    传送门

    Objective-C Runtime 是什么?

    Object-C的runtime是一个运行时库(官方传送门:https://opensource.apple.com/tarballs/objc4/),是一套纯C(C和汇编)API,感兴趣的可以下载官方源码。Objective-C runtime 创建了所有需要的结构体,让 Objective-C 的面相对象编程变为可能。

    术语

    1、Objective-C runtime包括两个版本,Modern Runtime和 Legacy Runtime:

    • Modern Runtime(现代的Runtime):64 位的 Mac OS X 应用和所有 iPhone OS 的应用
    • Legacy Runtime: 所有 32 位的 Mac OS X 应用

    2、Method 有 2 种基本类型的方法:

    • Instance Method(实例方法):以 ‘-’ 开始,比如 -(void)doFoo; 在对象实例上操作
    • Class Method(类方法):以 ‘+’ 开始,比如 +(id)alloc。方法(Methods)和 C 的函数很像,是一组代码,执行一个小的任务。如- (NSString *)movieTitle

    3、Selector
    Selector 在 Objective-C 中 selector 只是一个 C 的数据结构,用于表示一个你想在一个对象上执行的 Objective-C 方法。

    4、Meta Classes
    类类型

    基础重点

    typedef struct objc_class *Class;  
    typedef struct objc_object {  
        Class isa;  
    } *id;  
    

    这段代码
    5、objc_class
    Objective-C 中 NSObject是大多数类的根类。

    @interface NSObject <NSObject> {  
        Class isa  OBJC_ISA_AVAILABILITY;  
    }  
    

    从中可以看出NSObject有一个isa属性,类型是Class。Class 是一个 objc_class 结构类型的指针

    struct objc_class {  
         struct objc_class *isa;  
      
         struct objc_class *super_class;   
         const char *name;    
         long version;  
         long info;  
         long instance_size;  
         struct objc_ivar_list *ivars;  
         struct objc_method_list **methodLists;  
         struct objc_cache *cache;  
         struct objc_protocol_list *protocols;  
    };  
    

    可以看到Objective-C对象系统的基石:struct objc_class结构如下:

    • isa指针:指向该对象所属类型的类型对象(Class Object)。在Objective-C中,类也是用对象来表示的,而类的isa指针指向它的metaclass(存储静态成员变量和类方法)。
    • super_class指针:指向父类。
    • name:类名称。
    • version:类的版本信息。
    • info:运行期使用的标志位,比如0x1(CLS_CLASS)表示该类为普通class,0x2(CLS_META)表示该类为 metaclass。
    • instance_size:实例大小,即内存所占空间。
    • ivars:指向成员变量列表的指针。
    • methodLists:根据标志位的不同可能指向不同,比如可能指向实例方法列表,或者指向类方法列表。
    • cache:因为Objective-C的消息转发需要查找dispatch table甚至可能需要遍历继承体系,所以缓存最近使用的方法。
    • protocols:类需要遵守的协议。

    6、objc_object
    objc_object 只有一个指向类的 isa 指针,就是我们说的术语 “isa pointer”(isa 指针)。

    7、isa 指针
    isa 指针是当你向对象发送消息时,Objective-C Runtime 检查一个对象并且查看它的类是什么然后开始查看它是否响应这些 selectors 所需要的一切。

    8、id指针
    id数据类型是一个指向struct objc_object结构的指针,这个指针包含一个纸箱objc_class结构的isa 指针。
    更确切地说,id是指向Class类型的指针,而Class又是指向struct objc_class结构的指针。

    9、 Class Cache
    就是class_object定义中的struct objc_cache *cache;
    当 Objective-C runtime 沿着一个对象的 isa 指针检查时,它会发现一个对象实现了许多的方法。然而你可能只调用其中一小部分的方法,也没有意义每次检查时搜索这个类的分发表(dispatch table)中的所有 selector。所以这个类实现了一个缓存,当你搜索一个类的分发表,并找到合适的 selector 后,就会把它放进缓存中。所以当 objc_msgSend() 在一个类中查找 selector 时会先查找类缓存。有个理论是,当你在一个类上调用了一个消息,你很可能之后还会调用它。

    runtime 常用开发应用场景

    http://www.jianshu.com/p/19f280afcb24,“白开水”的这篇文章介绍的很好,标题“面试、工作”就赢了

    • runtime 消息机制
      消息机制原理:对象根据方法编号SEL去映射表查找对应的方法实现。
      我们写 OC 代码,它在运行的时候也是转换成了 runtime 方式运行的。任何方法调用本质:就是发送一个消息(用 runtime发送消息,OC 底层实现通过 runtime 实现),每一个 OC 的方法,底层必然有一个与之对应的 runtime 方法。
      OC的函数调用成为消息发送,属于 动态调用过程。在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

    作用

    利用runtime 可以做一些OC不容易实现的功能:

    • 动态交换两个方法的实现(特别是交换系统自带的方法)
    • 动态添加对象的成员变量和成员方法
    • 获得某个类的所有成员方法、所有成员变量

    面试题
    1、method swizzling?

    2、objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?
    objc_msgSend()是[obj foo]的具体实现。
    在runtime中,objc_msgSend()是一个c函数,[obj foo]会被翻译成这样的形式objc_msgSend(obj, foo)。
    1、去obj的对应的类中找方法
    2、先找缓存,找不到再去找方法列表,
    3、再找父类,如此向上传递。
    4、最后再找不到就要转发。

    3、什么时候会报 Unrecognized selector 的异常?
    当调用对象的某个方法的时候, 如果在当前类中没有找到此方法, 那么就到当前类的父类中去寻找, 如果在父类中没有找到, 那么就去父类的父类中去寻找, 一直找到 NSObject 都没有这个方法, 就会报 Unrecognized selector 的异常.

    4、runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法) IMP寻址
    http://blog.csdn.net/dp948080952/article/details/52437451

    5、_objc_msgForward函数是做什么的,直接调用它将会发生什么?
    http://www.jianshu.com/p/04ba5f3bfc2b

    6、消息机制方法调用流程
    方法:实例方法,类方法
    http://www.jianshu.com/p/d5ca2cdd4fa7 对官方文档的翻译,略显粗糙,适用于我这种英文比较烂的童鞋😂

    相关文章

      网友评论

          本文标题:runtime

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