动态消息转发机制实例

【iOS底层】11:消息转发 一、msgSend消息发送监听 在探索了很多次了lookUpImpOrForward方法中,查找完成后会写入cache 在写入cache中发现有个打印log的操作 我们来看下是否可以通过这个输出到本地的日志,是否可以查看到一些不一样的流程和我们还没探索过的方法。 上图中看到如果想要调用logMessageSend方法,需要满足判断条件:objcMsgLogEnabled && implementer,implementer是我们传入的class,那么影响判断的就只有o.. 阅读详情

Obective-C是由smalltalk演化而来,方法的调用实际上是消息的传递。这篇通过实例来证明动态动态消息转发机制

在Xcode中新建一个Command-Line Tool工程,在工程中New File一个Person类

在Person类中添加如下代码:

@interface Person : NSObject

- (void)run;

@end

@implementation Person

- (void)run
{
    NSLog(@"Person run");
}
@end

在main.m主程序中添加如下代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        [person run];
    }
    return 0;
}

运行程序可以在控制台打印出

Person run

该过程实际的操作是向person对象发送run的消息。如果person无法响应run方法的话就会抛出如下错误:

* Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[Person run]: unrecognized selector sent to instance

然而从person开始寻找run方法到抛出错误其实是经过了一个很『漫长』的过程。因为当某个类无法响应一个消息的时候,Objective-C会给你补救的机会。有如下三种补救的方式

  • 方法一

    +(BOOL)resolveInstanceMethod:(SEL)sel // 挽救实例方法

    +(BOOL)resolveClassMethod:(SEL)sel // 挽救类方法

  • 方法二

    -(id)forwardingTargetForSelector:(SEL)aSelector

  • 方法三

    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;

    -(void)forwardInvocation:(NSInvocation *)anInvocation;

方法一

在Person类中将run方法注释并加入如下代码:

/**
 *  消息转发自己类
 */
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(run)) {
        class_addMethod(self, sel, (IMP)run, nil);
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void run (id self, SEL _cmd)
{
    NSLog(@"%@, %s",self, sel_getName(_cmd));
}

运行程序,在未实现run方法的情况下并没有崩溃而是在控制台有如下输出:

, run

该方法run消息的响应还是在本类中。

方法二

该方法可以将消息转发到其他类中,为了演示我们新建一个Car类
在Car类中实现如下方法:

- (void)run
{
    NSLog(@"Car run");
}

我们在本类中添加forwardingTargetForSelector指明要转发到的类:

/**
 *   消息转发它类
 */
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return [[Car alloc] init];
}

运行程序可以在控制台看到有如下输出:

RunTimeTest[47071:7072728] Car run
person成功的将run消息转发给了Car类

方法三

首先runtime发送methodSignatureForSelector:消息查看Selector对应的方法签名,即参数与返回值的类型信息。如果有方法签名返回,runtime则根据方法签名创建描述该消息的NSInvocation,向当前对象发送forwardInvocation:消息,以创建的NSInvocation对象作为参数;若methodSignatureForSelector:无方法签名返回,则向当前对象发送doesNotRecognizeSelector:消息,程序抛出异常退出。

我们在Person中添加如下两个方法:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSString *sel = NSStringFromSelector(aSelector);
    if ([sel isEqualToString:@"run"]) {
        NSString *string = @"v@:";
        const char *types = [string UTF8String];
        return [NSMethodSignature signatureWithObjCTypes:types];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL selector = [anInvocation selector];
    Car *car = [[Car alloc] init];
    if ([car respondsToSelector:selector]) {
        [anInvocation invokeWithTarget:car];
    }
}

运行程序可以在控制台看到有如下输出:

RunTimeTest[47071:7072728] Car run

说明Person类成功的转发了消息。

关于生成签名的类型”v@:”解释一下。每一个方法会默认隐藏两个参数,self、_cmd,self代表方法调用者,_cmd代表这个方法的SEL,签名类型就是用来描述这个方法的返回值、参数的,v代表返回值为void,@表示self,:表示_cmd。

​
iOS——消息传递和消息转发机制 首先我们了解了什么是消息发送,明白了OC语言中所有对象的方法调用都是消息发送。其次我们知道了消息发送是SEL-IMP的查找过程调用resolveInstanceMethod或者resolveClassMethod作为动态解析方法给本类一个补救的方法去动态添加没有实现的方法的实现调用forwardingTargetForSelector让别的对象去执行这个函数(消息转发)forwardInvocation灵活的将目标函数以其他形式执行(我们的这个完整的消息转发的实现可以很简单https。... 阅读详情

相关推荐

iOS 方法动态决议和消息转发机制

iOS 方法动态决议和消息转发机制1. 动态方法决议1.1 实例方法动态解析 _class_resolveInstanceMethod1.2 _class_resolveClassMethod小结2. 消息转发2.1 快速转发流程2.2 慢速转发流程总结 通过上一篇章的学习,OC调用方法,底层是调用 objc_msgSend 发送消息。在发送消息时会经过一系列的...

LiangliangSpeak的博客 471

方法的动态决议,消息的转发

方法动态决议 动态决议 resolveInstanceMethod 当我们调用方法的时候,如果调用的是没有实现的实例的方法。那么我们可以通过runtime的运行机制以及动态决议: +(BOOL)resolveInstaceMethod:(SEL)sel; 来动态地给方法添加实现 如果面对类方法就是: +(BOOL)resolveClassMethod:(SEL)sel; runtime动态地添加实现imp的API是: +(BOOL)resolveInstanceMehod:(SEL)sel{ if(.

lingjunjie的博客 573

iOS runtime探究(二): 从runtime开始深入理解OC消息转发机制

你要知道的runtime都在这里转载请注明出处 http://www.jianshu.com/p/eac6ed137e06本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性proper

什么都不会的小菜鸟 3644

消息转发: methodSignatureForSelector + forwardInvocation

      在object-C中,我们可以向一个实例发送消息,这类似于其他编程语法中的方法调用,实例收到消息后,会进行一些处理:例如实例收到消息后,如果能respondsToSelector,那么就调用相应的方法,如果不能response一般情况会crash。下面通过方面减少这种crash。             实例收到消息后,一般的处理流程如下:       1,发送消息,如[ob...

iteye_14850的博客 470

NSObject中methodSignatureForSelector、forwardInvocation两个消息方法

NULL 博文链接:https://justsee.iteye.com/blog/1931346

im-ambassador:即时聊天消息转发器

IM Ambassador 这是从 精简而来的即时聊天消息转发器。 名字的「Ambassador」意为「使者」,「IM」意为「即时聊天」,也可理解为「我是」,寓意这个 bot 在多个即时聊天平台承担使者的角色,按某一既定规则转发、回复消息。 转发规则可通过配置文件设置,自定义性比较强。另外,消息发送器采用适配器模式,易于扩展不同的 IM 平台。目前仅支持接收和发送基于 、、 的消息。 重要:目前实现还非常粗糙,我也不一定有时间去改进。另外,完全没有做对于不同消息源的非文字消息的适配,所以按需谨慎使用。目前最建议的使用场景是使用一个酷 Q 程序进行 QQ 号之间的转发,也就不存在非文字消息的适配问题。 使用场景 将多个小号收到的消息转发到大号,并在大号里直接回复 将微信收到的消息转发到 QQ,并在 QQ 里直接回复 仅将某几个群的包含某几个关键词的消息转发到另一个账号 对同一个社区在不同平

使用methodSignatureForSelector与forwardInvocation实现消息转发 (转)

转自:http://blog.sina.com.cn/s/blog_8c87ba3b0102v006.html 在给程序添加消息转发功能以前,必须覆盖两个方法,即methodSignatureForSelector:和forwardInvocation:。methodSignatureForSelector:的作用在于为另一个类实现的消息创建一个有效的方法签名,必须实现,并且返回不...

306

Delphi进程间传递消息(发送和接收系统消息)..rar

Delphi进程间传递消息(发送和接收系统消息)..rar

动态方法决议&消息转发

探究动态方法决议和消息转发

weixin_38016552的博客 325

内存乒乓缓存机制和消息分发机制的C代码实现

用C代码实现乒乓内存缓冲机制,具体实用价值,帮助您提高内存响应速度与及时数据的处理。

k8s集群部署私有镜像仓库

本文介绍了在Kubernetes集群中部署私有镜像仓库的完整方案。使用registry:2镜像创建Deployment,通过NodePort(30500)暴露服务,并采用hostPath(/data/registry)实现数据持久化。部署过程包括节点标记、YAML配置、资源创建及验证步骤,同时提供了Docker和Containerd两种环境下的详细使用方法,包括配置不信任私有仓库、镜像推送/拉取操作指南。该方案特别适合开发测试环境,为团队提供便捷的本地镜像管理能力。

weixin_42728286的博客 893

Runtime(二)动态添加方法以及消息转发机制

runtime中函数的调用: 下面一张图详细的概括了每个函数调用的先后以及执行的前提: 1.对象在收到无法解读的消息后,首先会调用所属类的 + (BOOL)resolveInstanceMethod:(SEL)sel 这个方法在运行时,没有找到SEL的IML时就会执行。这个函数是给类利用class_addMethod添加函数的机会。根据文档,如果实现了添加函数代码则返回YES,未实现返回N

ideas press的专栏 1046

K230开发板实战:5步搞定YOLOv8模型部署(附常见报错解决方案)

本文提供了一份详细的K230开发板部署YOLOv8模型的实战教程。内容涵盖从环境准备、模型转换到代码编写的完整流程,并重点解析了使用AICube工具链时常见的“生成部署文件异常”等报错解决方案,旨在帮助开发者高效完成嵌入式AI模型部署。

weixin_29053073的博客 784

轻松学习之 Objective-C消息转发

我们要通过一个小例子来简单、通俗的理解一下什么是消息转发以及如何消息转发,希望看完这篇文章时大家会彻底的明白OC的消息。 首先,你需要知道这两个概念: OC中调用方法就是向对象发送消息。 比如 : 1 [person run]; 这实际上这是在给person这个对象发送run这个消息。 那

lkeplei的专栏 538

告别TI官网迷路!手把手教你用C2000Ware为TMS320F28027搭建Proteus仿真工程模板

本文详细指导如何使用C2000Ware为TMS320F28027搭建Proteus仿真工程模板,帮助DSP开发者快速上手。从资源获取、工程目录设计到关键文件配置,再到CCS与Proteus的联调技巧,全面解析仿真工程搭建的每个步骤,特别适合初学者和工程师参考。

weixin_42715608的博客 472

OpenClaw 报错 TypeError: Cannot read properties of undefined (reading ‘prototype‘):Node.js 版本不兼容

国产化环境中部署OpenClaw云边协同平台时,出现"TypeError: Cannot read properties of undefined (reading 'prototype')"报错。经分析发现根本原因是Node.js版本与依赖生态不兼容,新版本Node(如v21)移除了旧依赖使用的内部API。解决方案包括:1)使用nvm切换至兼容的Node 16/18 LTS版本;2)容器化部署固定Node版本;3)遵循官方推荐的引擎版本范围。该问题揭示现代工程中版本管理的重要性,

博客 2313

iOS-消息转发机制

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34195546的博客 114

为什么 ChatGPT 生成的下载地址会长成 sky-metal-cards-jerry.quirkypony34.chatgpt.site 这种奇怪的样子

我今天看到的这条地址,确实很容易让人产生一种感觉,ChatGPT 明明只是生成了几张 PNG 图片和一个压缩包,为什么最终拿到的却不是类似这种看起来很正规的下载链接,而是一长串带有、UUID、apidecks的地址。更容易让人疑惑的是,其中还出现了一个平时很少见到的域名。这并不是浏览器随机生成的临时 URL,也不是某个来历不明的第三方文件服务器。根据 OpenAI 在 2026 年公布的 ChatGPT Sites 文档和相关服务条款,

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 60

【iOS】—— 消息传递和消息转发

检查接受者是否存在,为nil则不做任何处理;通过receiverdeisa指针找到对应的class类对象;找到类对象之后通过内存平移找到cache;从cache中获取buckets;从buckets中对比sel,查看是否有同名方法;如果有对应的sel,就会进入到cacheHit,调用imp;如果没有对应的sel,进入objc_msgSend_uncached,然后到lookUpImpOrForward(慢速查找)。

qq_72437394的博客 2073

MAC-电脑中的user文件夹在哪?

MAC-电脑中的user文件夹在哪?

兴趣是最好的老师 1万+

通信算法之325:无人机云哨协议及发射机接收机仿真算法

【代码】通信算法之325:无人机云哨物理层协议及发射机接收机仿真代码。

leegang12的专栏 362

iOS runtime 完整消息转发 机制

上一篇我们测试了 备用者消息转发 机制, 也就是- (id)forwardingTargetForSelector:(SEL)aSelector 如果我们这个函数返回 nil, 那么就会进入到完整消息转发机制,也就是- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 函数。 如果没有在这个函数提供处理,那么就...

tangaowen的专栏 868

29.Labview界面设计 --- (下篇)自定义控件库、界面布局与外观设计

1.自定义控件外观(自定义控件)1.1 自定义外观库1.2 手动自定义控件外观2. 前面板控件布局方式(控件排布)2.1 模块化控制布局方式2.2 数据采集布局方式3. 前面板外观优化项(背景设计)3.1 前面板背景设计3.2 前面板窗口整理本节第一部分教大家安装一种可以直接用的自定义控件库,第二部分教大家如何自己设计控件并保存调用。

关注我,更多技术问题欢迎私聊~ 4781

iOS-消息转发和应用

对象收到一个它无法响应的方法到崩溃; 消息转发机制共分为3大步骤: 1、动态解析。先询问接受者的类所属的类,看看有没有动态的添加方法。resolveInstanceMethod,resolveClassMethod 2、快速消息转发。如果1执行完了也没有动态新增方法,那运行期系统就请接收者看看有没有其他对象能处理这条有消息,有的话就把消息转发给哪个对象。forwardingTargetForSelector 3、完整的消息转发机制。如果2没有,那运行期系统会把消息有关的全部细节写到NSInvocat

iOS轰炸机的博客 562

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

理解Objective-C Runtime(三)消息转发机制

消息转发机制概述 上一篇博客消息传递机制中讲解了Objective-C中对象的「消息传递机制」。本文需要讲解另外一个重要问题:当对象受到无法处理的消息之后会发生什么情况? 显然,若想令类能理解某条消息,我们必须以程序代码实现出对应的方法才行。但是,在编译期向类发送了其无法理解解读的消息并不会报错,因为在运行期间允许继续向类中添加方法,所以,编译器在编译期间还无法确知类中到底会不会有个...

dingzhengkuang5981的博客 206

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

个人对iOS OC 消息转发机制的基本原理理解

关于OC的消息转发机制,是大部分面试官在面试过程中经常问到的问题。在此我整理了一下我对OC消息转发机制的理解。 众所周知OC的一个对象在发送消息的时候首先在该类的struct objc_method_list列表中去搜索,如果找到则直接调用相关方法的实现,如果没有找到就会通过super_class指针沿着继承树向上去搜索,如果找到就跳转,如果到了继承树的根部(通常为NSObject)还没有找到。那...

weixin_34144848的博客 233

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

上一篇: UIScreenEdgePanGestureRecognizer无法响应/失效
下一篇: IPA的4种打包方式
joneOS
博客等级 码龄12年 1粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值