msgSend 流程详解

1.编译阶段

用户调用一个普通函数
[anObject doTings:things];
编译器会把其编译为:
objc_msgSend(anObject, @selector(doThings:), things);
注意:根据函数返回值的不同,编译器还会将其编译为objc_msgSend_stret、objc_msgSend_fpret等。但是,实现大同小异。这里只以objc_msgSend为例进行讨论。

2.msgSend概述

objc_msgSend实现大致如下:
id objc_msgSend(id self, SEL _cmd, ...){
Class class = object_getClass(self;)
IMP imp = cache_lookup(c, _cmd);
if(!imp){
imp = class_getMethodImplementation(class, _cmd);
}
return imp ? imp(self, _cmd, ...) : 0
}

由此可见,其主要功能可分为获取函数imp和调用imp两块。

3.msgSend整体流程

Step1. dispatch table中搜索selector的imp。这步大家应该都清楚,子类找不到,就去搜索父类,依次往上遍历。
注:dispatch table是编译时生成的selector与imp的对应表

Step2. 如果子类和所有父类的dispatch table中都没找到,就到动态解析。
很多人可能认为,这个曲折的寻找过程是必不可少的。其实并不是这样的。可以将子类中某个方法的imp直接设置成objc_msgForward,就可以直接进入转发流程。

Step3.函数调用
这里着重介绍下转发机制(__forwarding__)的实现。其代码大致如下:

这里不做详细分析,简要说下我认为有用的几点:
a.为何有了forwardingInvoaction,还需要fowardingTarget?
因为fowardingTarget不涉及参数解析与封装,只是简单的把target替换下,就立马进入下一轮msgSend,所以效率较高,是首选。只有当涉及参数处理时,才有必要在forwardingInvoaction中干。

b.为什么forwardingInvoaction前,需要获取methodSignature?
单靠selector,无法完成对参数的解析,从而无法完成对target、selector和参数的打包。此时,需要获取method signature(包含参数、返回值的所有信息)来协助完成对参数的解析。

objc_msgForward和其他函数imp一样,都是函数指针
objc_msgForward和其他函数imp一样,都是函数指针
objc_msgForward和其他函数imp一样,都是函数指针
重要的事情说三遍

参考文献

[1] What's that Selector?
[2] Effective Objective-C 2.0:编写高质量iOS与OS X代码的52个有效方法

时间: 2024-08-06 19:57:11

msgSend 流程详解的相关文章

微信支付的开发流程详解_php技巧

最近在公司做了微信支付的接入,这里总结下开发的一些经验 注意,我使用的是微信开放平台的支付,与手机app相关,而与公众账号无关. 微信支付的主要操作流程 1.用户浏览app,选定商品然后下单. 2.服务器处理订单逻辑,开始正式发起支付流程 3.首先,后台服务器向weixin服务器发起请求,获取一个token. 4.后台服务器拿到token,使用和其他参数加密,再次向weixin服务器发起请求,获取一个预支付prepayid 5.后台服务器将该prepayid返回给app客户端 6.app调用手机

Android编程输入事件流程详解_Android

本文实例讲述了Android编程输入事件流程.分享给大家供大家参考,具体如下: EventHub对输入设备进行了封装.输入设备驱动程序对用户空间应用程序提供一些设备文件,这些设备文件放在/dev/input里面. EventHub扫描/dev/input下所有设备文件,并打开它们. bool EventHub::openPlatformInput(void) { ... mFDCount = 1; mFDs = (pollfd *)calloc(1, sizeof(mFDs[0])); mDev

Android Bluetooth蓝牙技术使用流程详解_Android

在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto

app发布流程详解

app发布流程详解  https://developer.apple.com   1. 点击 Member Center   2. 创建应用ID   3. 创建项目   4. 在AppStore创建对应的应用   5. 创建授权文件   6. 配置授权文件   7. 打包项目   8. 提交审核之前添加应用           - 说明 - 提交审核过程较为复杂,步骤大致是: 1. 创建应用id 2. 根据创建出来的应用id创建出对应标示的项目(本地 + Appstore) 3. 配置证书以及授

ReentrantLock的lock-unlock流程详解

[本文转载自ReentrantLock的lock-unlock流程详解] 最近一段时间在研究jdk里的concurrent包,分为了线程管理,锁操作以及原子操作三个部分.线程管理平时用得还算多,但是锁操作和原子操作基本就没用过,只是以前在大学的时候跑了几个例子玩玩.当看到ReentrantLock的时候,发现用法倒是和synchronized有点类似也很简单,但是内部原理比较复杂.网上查了关于ReentrantLock的相关内容,没发现有谁把它分析得很透彻,只是有几篇讲了内部的锁实现机制,只可惜

Linux系统启动流程详解

那篇文章不涉及操作系统,只与主板的板载程序有关.今天,我想接着往下写,探讨操作系统接管硬件以后发生的事情,也就是操作系统的启动流程. 这个部分比较有意思.因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多:但是,一旦进入操作系统,程序员几乎可以定制所有方面.所以,这个部分与程序员的关系更密切. 我主要关心的是Linux操作系统,它是目前服务器端的主流操作系统.下面的内容针对的是Debian发行版,因为我对其他发行版不够熟悉. 第一步.加载内核 操作系统接管硬件以后,首先读入

Android Bluetooth蓝牙技术使用流程详解

在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto

SEO作业流程详解

详解|seo 第一个就是要看网站的排名成长幅度跟状况,来作更进一步的修正.第二个就是根据现阶段搜寻引擎喜好的部分作微调,并且持续加强您网站的基本面. SEO的作业流程是琐碎繁杂的.大致先可切割成两个部分,前期建置与每个月的维护.前期建置作业固定流程: Keyword and Audience Analysis(关键词与目标客群关联分析) Detailed Competition Analysis(竞争对手分析) Content Quality Enhancement(强化内容质量) Search

PHP入门教程之操作符与控制结构流程详解_php技巧

本文实例讲述了PHP入门教程之操作符与控制结构流程.分享给大家供大家参考,具体如下: Demo1.php <?php $username = "chaoyv"; echo "His name is $username !"; $username2 = "吴者然"; echo "His name is $username2 ! "; echo "<br/>"; echo "His