2018-02-01

《Objective-C runtime系列  1》消息发送及转发机制

    Objective-C是基于C,加入了面向对象面向对象特性和消息转发机制的动态语言,Runtime系统来动态创建类和对象进行消息发送和转发。

一,ObjC的消息发送机制    

在ObjC中用某对象调用方法时  [receiver message],会被runtime转换成

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

下面用代码形式说明一下消息发送机制。向Test实例发送print消息

2018-02-01_第1张图片

我们用clang编辑器的命令clang -rewrite-objc main.m,把下边代码转换成.cpp文件,转化后在文件夹下生成了一个大约十万行代码的main.cpp文件。翻到最下边,找到我们要找的main函数中的代码。 如图


2018-02-01_第2张图片

由上图代码可以看出,[test print]代码被转化成了 

 ((void (*)(id, SEL))(void *)objc_msgSend)((id)test, sel_registerName("print"));

其中(id)test代表我们的test对象。 sel_registerName("print")则代表了SEL方法选择器。 

1.1  Runtime数据结构

如图,id是一个通用类型的指针,指向任何OC对象,能表示任何对象,

struct objc_object {

    Class _Nonnull isa __attribute__((deprecated));

};

/// A pointer to an instance of a class.

typedef struct objc_object *id;

其实id就是指向objc_object结构体类型的指针,它包含一个class isa变量。 根据isa可以顺藤摸瓜找到对应的类。 

typedef struct objc_selector *SEL;

其实它就是映射到方法的C字符串,你可以通过ObjC编译器命令@selector()或者Runtime系统的sel_registerName函数来获取一个SEL类型的方法选择器。

如果你知道selector对应的方法名是什么,可以通过NSString* NSStringFromSelector(SEL aSelector)方法将SEL转化为字符串,再用NSLog打印。

Class

    isa指针的类型是Class,Class表示所属对象的类。 

typedef struct objc_class *Class;

可以看出,Class其实是指向objc_class结构体的指针。在runtime.h文件中我们找到objc_class的定义,如下图


2018-02-01_第3张图片

isa表示Class对象的Class,也就是Meta Class(元类)。

objc_ivar_list是属性列表,其实是一个链表,存储着多个objc_ivar.

ojcg_method_list是方法列表, 也会一个链表,存放着多个objc_method;

objc_cache用来缓存经常用到的方法。 

objc_protocol_lists表示类遵从哪些协议。

1.2 objc_msgSend函数

根据receiver对象的isa指针获取它对应的class;

优先在class的cache查找message方法,如果找不到,到methodlists中查找。 

如果没有找到,再到super_class查找。 

一旦找到message方法,就执行它的实现IMP。

一直找不到时,就会进入消息转发机制。 下篇继续~

你可能感兴趣的:(2018-02-01)