美文网首页
2018-02-01

2018-02-01

作者: 飞熊_V | 来源:发表于2018-02-01 16:33 被阅读0次

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

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

    一,ObjC的消息发送机制    

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

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

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

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

    由上图代码可以看出,[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的定义,如下图

    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

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