Runtime

2018/5/16 posted in  iOS

一、基本概念

  1. RunTime简称运行时,就是系统在运行的时候的一些机制,其中最主要的是消息机制。
  2. 对于C语言,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,无任何二义性。
  3. OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。
  4. 只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。

二、Runtime - 消息机制

#import <objc/message.h>

底层函数调用都是通过消息发送的 objc_msgSend

例如:

Person * p = [[Person alloc] init];

Person * p = objc_msgSend([Person class], @selector(alloc));
Person * p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));

p = [p init];
p = objc_msgSend(p, sel_registerName("init"));

[p eatWith:@"food"];
objc_msgSend(p, sel_registerName("eatWith:"),@"food");

验证:clang 编辑器,生成 main.cpp 文件

$ clang -rewrite-objc main.m

三、Runtime - 运行时机制

<Objc/runtime.h>

苹果提供的一套C语言的API,可以再OC编译运行的阶段,动态的改变操作

SEL 方法编号
IMP 方法实现(本质是函数指针)
在OC中我们调用方法都是通过消息机制,给某个对象发送编号消息,通过SEL 可以找到对应的IMP
SEL 和 IMP是一一对应的关系

编程思想:面向切面编程(AOP) 核心的技术就是用到了HOOK(钩子)思想
改变原来的方法调用顺序

三、常见的作用

  1. 动态的添加对象的成员变量和方法
  2. 动态交换两个方法的实现(Method Swizzling)
  3. 实现分类也可以添加属性
  4. 实现NSCoding的自动归档和解档
  5. 实现字典转模型的自动转换

runtime 相关定义

/// 描述类中的一个方法
typedef struct objc_method *Method;

/// 实例变量
typedef struct objc_ivar *Ivar;

/// 类别Category
typedef struct objc_category *Category;

/// 类中声明的属性
typedef struct objc_property *objc_property_t;


//类在runtime中的表示
struct objc_class {
    Class isa;//指针,顾名思义,表示是一个什么,
    //实例的isa指向类对象,类对象的isa指向元类

#if !__OBJC2__
    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 //协议列表
    #endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */