iOS - 消息机制

1. 基本数据结构

// 方法结构
struct method_t {SEL name;       // 方法名const char *types;  // 类型编码IMP imp;       // 方法实现
};// 类结构
struct objc_class {Class isa;Class superclass;cache_t cache;        // 方法缓存class_data_bits_t bits;  // 类的方法、属性等信息
};// 方法缓存
struct cache_t {struct bucket_t *_buckets;  // 散列表mask_t _mask;              // 容量掩码mask_t _occupied;          // 已使用数量
};

2. 消息发送流程

2.1 基本流程

// 消息发送入口
id objc_msgSend(id self, SEL _cmd, ...) {if (!self) return nil;// 1. 查找方法缓存IMP imp = cache_getImp(self->isa, _cmd);if (imp) return imp(self, _cmd, ...);// 2. 完整查找流程return _objc_msgSend_uncached(self, _cmd, ...);
}

2.2 方法查找

IMP lookUpImpOrForward(id obj, SEL sel) {Class cls = obj->getIsa();// 1. 查找当前类的方法Method method = class_getInstanceMethod(cls, sel);if (method) {// 加入缓存cache_fill(cls, sel, method->imp);return method->imp;}// 2. 查找父类方法for (Class tcls = cls->superclass; tcls; tcls = tcls->superclass) {method = class_getInstanceMethod(tcls, sel);if (method) {cache_fill(cls, sel, method->imp);return method->imp;}}// 3. 动态方法解析if (resolveInstanceMethod(cls, sel)) {return lookUpImpOrForward(obj, sel);}// 4. 消息转发return _objc_msgForward;
}

3. 方法缓存机制

3.1 缓存结构

struct cache_t {// 缓存桶struct bucket_t {SEL _sel;   // 方法名IMP _imp;   // 方法实现} *_buckets;// 查找方法IMP imp(SEL sel) {bucket_t *b = buckets();mask_t m = mask();mask_t begin = cache_hash(sel, m);mask_t i = begin;do {if (b[i].sel() == sel) {return b[i].imp();}} while ((i = cache_next(i, m)) != begin);return nil;}
};

3.2 缓存优化

// 缓存哈希算法
static inline mask_t cache_hash(SEL sel, mask_t mask) {return (mask_t)(uintptr_t)sel & mask;
}// 缓存扩容
void cache_t::expand() {uint32_t oldCapacity = capacity();uint32_t newCapacity = oldCapacity ? oldCapacity * 2 : INIT_CACHE_SIZE;if (newCapacity > MAX_CACHE_SIZE) {newCapacity = MAX_CACHE_SIZE;}reallocate(oldCapacity, newCapacity);
}

4. 消息转发机制

4.1 动态方法解析

+ (BOOL)resolveInstanceMethod:(SEL)sel {if (sel == @selector(someMethod:)) {class_addMethod(self,sel,(IMP)dynamicMethodIMP,"v@:");return YES;}return [super resolveInstanceMethod:sel];
}

4.2 快速转发

- (id)forwardingTargetForSelector:(SEL)aSelector {if (aSelector == @selector(someMethod:)) {return alternateObject;  // 转发给其他对象}return [super forwardingTargetForSelector:aSelector];
}

4.3 完整转发

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {if (aSelector == @selector(someMethod:)) {return [NSMethodSignature signatureWithObjCTypes:"v@:"];}return [super methodSignatureForSelector:aSelector];
}- (void)forwardInvocation:(NSInvocation *)anInvocation {if ([alternateObject respondsToSelector:[anInvocation selector]]) {[anInvocation invokeWithTarget:alternateObject];} else {[super forwardInvocation:anInvocation];}
}

5. 性能优化

5.1 方法缓存

// 缓存命中检查
static ALWAYS_INLINE IMP cache_getImp(Class cls, SEL sel) {cache_key_t key = cache_key(sel);bucket_t *buckets = cls->cache.buckets();mask_t mask = cls->cache.mask();bucket_t *bucket = &buckets[key & mask];if (bucket->key() == key) {return bucket->imp();}return nil;
}

5.2 方法内联

// 编译器优化
static ALWAYS_INLINE id 
objc_msgSendSuper2(struct objc_super2 *super, SEL op, ...) {return ((id (*)(struct objc_super2 *, SEL, ...))objc_msgSendSuper2_fixup)(super, op, ...);
}

6. 特殊情况处理

6.1 nil 消息

if (!self) return nil;  // 发送给 nil 的消息返回 nil

6.2 Tagged Pointer

if (objc_isTaggedPointer(obj)) {// 特殊处理 Tagged Pointerreturn objc_msgSend_tagged(obj, sel, ...);
}

7. 线程安全

7.1 缓存更新

static void cache_fill(Class cls, SEL sel, IMP imp) {cache_t *cache = &cls->cache;cache->mutex.lock();// 更新缓存cache->insert(sel, imp);cache->mutex.unlock();
}

7.2 方法添加

static IMP addMethod(Class cls, SEL name, IMP imp, const char *types) {mutex_locker_t lock(runtimeLock);IMP result = nil;if (addMethodNoLock(cls, name, imp, types, &result)) {// 更新方法缓存flushCaches(cls);}return result;
}

这个消息机制设计的关键点:

  1. 高效的方法查找
  2. 灵活的消息转发
  3. 优秀的缓存策略
  4. 完善的线程安全
  5. 特殊情况的处理

这些特性使得 Objective-C 的消息机制既灵活又高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(已开源-AAAI25) RCTrans:雷达相机融合3D目标检测模型

在雷达相机融合三维目标检测中,雷达点云稀疏、噪声较大,在相机雷达融合过程中提出了很多挑战。为了解决这个问题,我们引入了一种新的基于query的检测方法 Radar-Camera Transformer (RCTrans)。具体来说: 首先设计了一个雷达稠密…

Python----Python爬虫(利用bs4、pyquery、xpath爬取电影名和评分)

电影网址电影大全_好看的电影_最新好看的电影_电影排行榜-影视快搜 一、bs4 import requests from fake_useragent import UserAgent from bs4 import BeautifulSoup # 设置URL地址 urlhttp://kan.znds.com/movie/ # 设置请求头 headers{User-Agent:UserAgent().edge} # 发送…

Hbuilder ios 离线打包sdk版本4.36,HbuilderX 4.36生成打包资源 问题记录

1、打包文档地址https://nativesupport.dcloud.net.cn/AppDocs/usesdk/ios.html#%E9%85%8D%E7%BD%AE%E5%BA%94%E7%94%A8%E7%89%88%E6%9C%AC%E5%8F%B7 2、配置应用图标 如果没有appicon文件,此时找到 Assets.xcassets 或者 Images.xcassets(看你sdk引入的启动文件中…

TCP通信原理学习

TCP三次握手和四次挥手以及为什么_哔哩哔哩_bilibili

unity学习13:gameobject的组件component以及tag, layer 归类

目录 1 gameobject component 是unity的基础 1.1 类比 1.2 为什么要这么设计? 2 从空物体开始 2.1 创建2个物体 2.2 给 empty gameobject添加组件 3 各种组件和新建组件 3.1 点击 add component可以添加各种组件 3.2 新建组件 3.3 组件的操作 3.4 特别的…

MYSQL--------什么是存储过程和函数

什么是存储过程和函数 存储过程: 存储过程是一组预编译的 SQL 语句集合,存储在数据库服务器中,可通过名称调用执行。它可以包含数据操作语言(DML)、数据定义语言(DDL)、控制流语句等。存储过程主…

计算机网络 (30)多协议标签交换MPLS

前言 多协议标签交换(Multi-Protocol Label Switching,MPLS)是一种在开放的通信网上利用标签引导数据高速、高效传输的新技术。 一、基本概念 MPLS是一种第三代网络架构技术,旨在提供高速、可靠的IP骨干网络交换。它通过将IP地址映…

探索Facebook的区块链计划:未来社交网络的变革

随着区块链技术的迅速发展,社交网络领域正面临一场深刻的变革。Facebook,作为全球最大且最具影响力的社交平台之一,正在积极探索区块链技术的应用。本文将深入探讨Facebook的区块链计划,分析其潜在的变革性影响,并展望…

十年后LabVIEW编程知识是否会过时?

在考虑LabVIEW编程知识在未来十年内的有效性时,我们可以从几个角度进行分析: ​ 1. 技术发展与软件更新 随着技术的快速发展,许多编程工具和平台不断更新和改进,LabVIEW也不例外。十年后,可能会有新的编程语言或平台…

C# async和await

第一种: 多个异步任务按照顺序执行先让一个异步任务start 然后通过ContinueWith方法 在参数函数的表达式里面开启第二个任务如果要有第三个任务 需要在第二个任务ContinueWith方法中开启第三个任务 以此类推 可以实现多个异步任务顺序执行 上面这种方式绘出现地狱回…

Excel 技巧03 - 如何对齐小数位数? (★)如何去掉小数点?如何不四舍五入去掉小数点?

这几个有点儿关联,我都给放到一起了,不影响大家分别使用。 目录 1,如何对齐小数位数? 2,如何去掉小数点? 3,如何不四舍五入去掉小数点? 1,如何对齐小数位数&#xff…

node.js|浏览器插件|Open-Multiple-URLs的部署和使用,实现一键打开多个URL的强大工具

前言: 在整理各类资源的时候,可能会面临资源非常多的情况,这个时候我们就需要一款能够一键打开多个URL的浏览器插件了 说简单点,其实,迅雷就是这样的,但是迅雷是基于内置nginx浏览器实现的,并…

“AI 视频图像识别系统,开启智能新视界

咱老百姓现在的生活啊,那是越来越离不开高科技了,就说这 AI 视频图像识别系统,听起来挺高大上,实际上已经悄无声息地融入到咱们日常的方方面面,给咱带来了超多便利。 先讲讲安防领域吧,这可是 AI 图像识别的…

C语言 游动的小球

代码如下&#xff1a; 在这里插入代码片#include<stdio.h> #include<stdlib.h> #include<windows.h>int main() {int i,j;int x 5;int y 10;int height 20;int velocity_x 1;int velocity_y 1;int left 0;int right 20;int top 0;int bottom 10;while(1){…

基于SpringBoot实现的保障性住房管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

安卓触摸对焦

1. 相机坐标说明 触摸对焦需要通过setFocusAreas()设置对焦区域&#xff0c;而该方法的参数的坐标&#xff0c;与屏幕坐标并不相同&#xff0c;需要做一个转换。 对Camera&#xff08;旧版相机API&#xff09;来说&#xff0c;相机的坐标区域是一个2000*2000&#xff0c;原点…

湖南引力:低代码技术助力军工企业实现设备管理系统创新

背景介绍 在核工业相关生产领域&#xff0c;随着技术的持续进步&#xff0c;生产活动对设备的依赖性日益增强。随着企业规模的不断扩大&#xff0c;所涉及的设备数量和种类也在急剧增长&#xff0c;这使得传统的设备管理模式逐渐显得力不从心。企业当前的设备管理主要依赖人工…

【701. 二叉搜索树中的插入操作 中等】

题目&#xff1a; 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多…

VR+智慧消防一体化决策平台

随着科技的飞速发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术与智慧城市建设的结合越来越紧密。在消防安全领域&#xff0c;VR技术的应用不仅能够提升消防训练的效率和安全性&#xff0c;还能在智慧消防一体化决策平台中发挥重要作用。本文将探讨“VR智慧消防一体化…

nginx http反向代理

系统&#xff1a;Ubuntu_24.0.4 1、安装nginx sudo apt-get update sudo apt-get install nginx sudo systemctl start nginx 2、配置nginx.conf文件 /etc/nginx/nginx.conf&#xff0c;但可以在 /etc/nginx/sites-available/ 目录下创建一个新的配置文件&#xff0c;并在…