Runtime 详解

目录
1、Runtime是什么?
2、Runtime的原理和分析。
3、Runtime的应用。

1、Runtime是什么?

Runtime 又叫运行时,是一套底层的C语言API,OC底层都是基于它来实现的。

OC是一门动态语言,它会将一些工作放在代码运行时才处理而并非编译时。也就是说,有很多类和成员变量在我们编译时是不知道的,而在运行时,我们所编写的代码会转换成完整的确定的代码运行。

所以,编译器时不够的,我们还需要一个运行时系统来处理编译后的代码(创建类和对象、进行消息传递和转发)。因此,这样的设计使 Objective-C 变得灵活,甚至可以让我们在程序运行的时候,去动态修改一个方法的实现。而实现这一切的基础就是 Runtime 。

2、Runtime的原理和分析

方法调用(消息传递)

typedef struct objc_class *Class;

Class 被定义为指向 objc_class 的指针,而 objc_class 本身是一个结构体。

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
#if !OBJC2

    Class Nullable super_class                              OBJC2UNAVAILABLE;
    const char * Nonnull name                               OBJC2UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * Nullable ivars                  OBJC2UNAVAILABLE;
    struct objc_method_list * Nullable * _Nullable methodLists                    OBJC2UNAVAILABLE;
    struct objc_cache * Nonnull cache                       OBJC2UNAVAILABLE;
    struct objc_protocol_list * Nullable protocols          OBJC2UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;

主要介绍两个参数:
isa,是一个Class类型的指针,每个实例对象都有一个isa指针,指向对象的类,类也可以通过isa找到它的原类。

cache,类缓存,为了加速消息分发,每次响应消息系统会对方法和对应的地址进行缓存,存放与cache中。再次调用时现在cache中查找,效率更快。

在OC中,方法调用的过程:
1、通过对象的 isa 指针找到对应的类。
2、通过类的 isa 指针找到对应元类。(基类的元类指向自己)
3、在元类的 methodLists 中,找到对应的方法,然后执行。

找到方法之后它是怎么执行的呢?

先看Method的定义

typedef struct objc_method *Method;
struct objc_method {
    SEL method_name;
    char * method_types;
    IMP method_imp;
};

Method 被定义为一个 objc_method 指针,在 objc_method 结构体中,包含一个 SEL 和一个 IMP 。
SEL ,可以看成保存方法名的一串字符。
IMP, 实现程序的内存地址的指针。

在OC中所有的方法调用都是给对象发消息。发消息主要使用的就是objc_msgSend 函数。

id objc_msgSend(id self, SEL op, ...);

举例:
[self doSomething];
objc_msgSend(self, @selector(doSomething));

当一个方法在所有继承的类中找不到时,会程序崩溃,但是之前会走拦截调用和消息转发流程。

完整的流程如示:

这样一来,我们可以重写 +resolveClassMethod: 和 +resolveInstanceMethod: 方法,在程序崩溃前做一些处理。

3、Runtime的应用

(1)具体应用拦截系统自带的方法调用及KVO的实现。
(2)实现给分类增加属性。
(3)实现字典与模型的自动切换。
(4)JSPatch替换已有的OC的方法。
(5)aspect 切面编程的应用。

你可能感兴趣的:(Runtime 详解)