mac开发系列23:runtime的基础知识

1、oc总是尽可能把更多的事情从编译时期和链接时期,推迟到runtime(运行时期)来动态执行。这就意味着oc不仅需要编译器,还需要一套runtime system来支撑它的运行。
2、oc程序通过以下3种方式跟runtime system进行交互:
1)通过oc源代码

2)通过定义在Foundation framework中的NSObject类的方法

3)直接调用runtime函数

3、
编译器会为每个类构建一个结构体,源码如下:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY; // oc中,类也是一种对象,类对象的isa指针指向元类

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; // 方法列表,表项包含方法对应的selector以及地址
struct objc_cache *cache OBJC2_UNAVAILABLE; // 缓存调用过的方法,加速方法查找
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议列表

endif

} OBJC2_UNAVAILABLE;

/// An opaque type that represents an Objective-C class. typedef struct objc_class *Class;

对象是类的实例,源码如下:
/// Represents an instance of a class.struct objc_object { Class isa OBJC_ISA_AVAILABILITY; // 指向类(对象),通过isa指针,对象可以访问它的类,进而访问到它的类的父类};

编译器把如下消息表达式:

[receiver message]

转成messaging function(消息发送函数),即 objc_msgSend:
objc_msgSend(receiver, selector)

objc_msgSend(receiver, selector, arg1, arg2, ...)

消息表达式直到runtime才和方法的实现绑定在一起。
objc_msgSend函数负责搞定动态绑定需要的一切:
1)查找selector对应的过程(方法的实现)。对于不同类实现的相同方法,根据receiver对应的类来精确区分定位。
2)然后调用过程,把receiver的指针以及相关的参数传给过程。
3)最后,把过程的返回值拿到当成自己的返回值。
动态绑定示意图如下:


当一个消息发送给一个对象时(实例对象或者类对象),objc_msgSend函数会根据isa指针去对象的类的方法列表里查找selector(selector可以看做方法的key);如果找不到,就顺着类的superclass去父类的方法列表里查找,以此类推,直到NSObject类(还找不到就会触发消息转发逻辑)。一旦找到,objc_msgSend函数就把接收消息的对象的结构体传给selector对应的方法。为了加快查找速度,runtime会缓存调用过的方法。
熟悉c++的同学知道,上述查找方法的流程在c++编译时也是这么干的,不同的是oc在运行时这么干而已,也因此oc被称为动态语言。
消息转发和基于method swizzling的hook方案,后续补上。
官方文档链接:
https://developer.apple.com/reference/objectivec/objective_c_runtime?language=objc
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008048?language=objc

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,856评论 0 9
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 787评论 0 2
  • 简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 O...
    专业男神经阅读 924评论 0 2
  • runtime 和 runloop 作为一个程序员进阶是必须的,也是非常重要的, 在面试过程中是经常会被问到的, ...
    made_China阅读 1,236评论 0 7
  • 前言 runtime其实在我们日常开发过程中很少使用到,尤其是像我现在比较初级的程序猿就更用不到了。但是去面试很多...
    WolfTin阅读 703评论 0 2