iOS - 消息机制

server/2025/1/11 7:13:12/

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.ppmy.cn/server/157400.html

相关文章

ubuntu22.04 的录屏软件有哪些?

在Ubuntu 22.04上,有几款适合做视频直播和录屏的软件: 1. OBS Studio (Open Broadcaster Software) 功能:OBS Studio 是最常用的开源直播和录屏软件,支持视频录制、直播流式传输,并且有强大的插件支持,能…

视频编辑最新SOTA!港中文Adobe等发布统一视频生成传播框架——GenProp

文章链接:https://arxiv.org/pdf/2412.19761 项目链接:https://genprop.github.io 亮点直击 定义了一个新的生成视频传播问题,目标是利用 I2V 模型的生成能力,将视频第一帧的各种变化传播到整个视频中。 精心设计了模型 GenProp&…

怎么修复损坏或者语法有问题的PDF-免费PDF编辑工具分享

序言 我之前的文章也有介绍过如何使用96缔盟PDF处理器修复破损或者语法有问题的PDF文件,但是当时是使用DMPDFUtilTool1.0版本进行的,V1.0的功能尚不完善,存在一些隐藏的功能BUG,而且在用户体验方面也存在一些不足,例如还不支持拖…

React PureComponent使用场景

1. 基本概念 1.1 什么是 PureComponent PureComponent 是 React 提供的一个优化类组件,它通过自动实现 shouldComponentUpdate 生命周期方法,对 props 和 state 进行浅比较来决定是否需要重新渲染组件。 1.2 与 Component 的区别 // 普通 Component …

从 0 到 1,用 FastGPT 搭建专属私有化知识库与超智能 AI 助理

田园课堂私有化知识库搭建流程与总结 引言 在当今数字化时代,知识管理与智能交互对于教育领域的创新发展至关重要。FastGPT作为一款高效的AI流程构建可视化开源工具,为田园课堂实现私有化知识库的快速搭建提供了有力支持。本文将详细阐述使用FastGPT搭…

【C++/控制台】2048小游戏

源代码&#xff1a; #include <iostream> #include <windows.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <conio.h> #include <time.h>// #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)…

【C++】揭开C++类与对象的神秘面纱(首卷)(类的基础操作详解、实例化艺术及this指针的深究)

文章目录 一、类的定义1.类定义格式2.类访问限定符3.类域 二、类的实例化1.实例化概念2.对象的大小 三、隐藏的this指针与相关练习1.this指针的引入与介绍练习1练习2练习3 一、类的定义 1.类定义格式 在讲解类的作用之前&#xff0c;我们来看看类是如何定义的&#xff0c;在C中…

HarmonyOS开发:ArkTS初识

ArkTS基本语法 ArkTS语言简介 ArkTS是鸿蒙生态的应用开发语言。基本语法风格与TypeScript&#xff08;简称TS&#xff09;相似&#xff0c;在TS的生态基础上进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 基本语法概述 扩展能力 基础语法&#xff1a…