美文网首页程序员
Runtime那点事儿

Runtime那点事儿

作者: Neebel | 来源:发表于2016-12-13 14:33 被阅读0次

Runtime是Objective-C语言的重要特性之一,也是Objective-C之所以能够成为动态语言的支柱。深入理解Runtime,有助于整体把握Objective-C语言的运行机制和原理。本篇文章主要内容有:

  • Runtime的概念
  • Runtime的相关术语解释
  • 消息机制

Runtime的概念

Objective-C是一门动态语言,动态语言和静态语言的区别在于将很多编译期的工作放在运行期做,实现了非常大的灵活性。Runtime就是保证Objective-C语言动态性的库,这个库底层由C语言实现,并且引入了多种结构体以支持OC中的类、对象等。

Runtime的相关术语解释

OC中对象和类的继承关系如下:

runtime0.png

实例对象的isa指针指向派生该对象的类,普通类的isa指针指向派生该类的元类,元类的isa指针指向根元类,根源类的isa指针指向自身。根元类由根类派生。所以,类的结构体里包含了众多信息:isa、父类、类名称、版本、信息等等:

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;

IMP

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id (*IMP)(id, SEL, ...); 
#endif

IMP是指向函数实现的指针,每一个函数对应一个IMP。

SEL

struct objc_selector {
    char *name;                       OBJC2_UNAVAILABLE;
    char *types;                      OBJC2_UNAVAILABLE;
};

selector是用来区别不同方法的标识。

其他类型结构体例如 objc_ivarobjc_methodobjc_propertyobjc_cacheobjc_category在源码中都有清楚的表示,并且比较容易理解,这里就不再列出。

消息机制

静态语言中,实例对象调用方法是在编译期就能够确定执行内容的,而OC中调用方法实际是对某个对象发送消息:例如 [anObject method] 表示对实例对象anObject发送了一条消息method,具体anObject是否执行method中的代码不确定。消息机制包括消息发送和消息转发两个过程。

消息发送

消息发送是通过selector查找IMP,找到后执行对应代码的过程。用流程图表示为:

runtime1.png

消息转发
消息转发是在IMP找不到的情况下,后续执行的流程。

runtime2.png

(1) resolveInstanceMethod返回YES,则消息处理放在这个方法中,可以通过添加方法实现。返回NO,则进入下一步。

(2)如果返回一个备选对象,则会调用该对象的方法,如果返回nil,则进入下一步。

(3)如果返回methodSignature,则进入下一步,如果返回nil,消息无法处理,Runtime会发出doesNotRecognizeSelector消息,程序崩溃。

(4)在forwardInvocation中,我们可以修改响应对象,修改方法实现等。

概括来说,消息转发是对消息发送时的异常情况做的补救措施。消息机制的源码分析(包括c语言和汇编)可以参照这篇博客,总结得很详细很好。

相关文章

网友评论

    本文标题:Runtime那点事儿

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