消息发送

消息发送举例:下面这个OC代码

[person read:book];

会被编译成:

objc_msgSend(person, @selector(read:), book);

objc_msgSend的具体流程如下:

  1. 通过isa指针找到所属类
  2. 查找类的cache列表, 如果没有则下一步
  3. 查找类的”方法列表”
  4. 如果能找到与选择子名称相符的方法, 就跳至其实现代码
  5. 找不到, 就沿着继承体系继续向上查找
  6. 如果能找到与选择子名称相符的方法, 就跳至其实现代码
  7. 找不到, 执行”消息转发”.

消息转发

上面我们提到, 如果到最后都找不到, 就会来到消息转发,消息转发的流程如下:

  1. 动态方法解析 : 先问接收者所属的类, 你看能不能动态添加个方法来处理这个”未知的消息”? 如果能, 则消息转发结束.
  2. 备胎(后备接收者) : 请接收者看看有没有其他对象能处理这条消息? 如果有, 则把消息转给那个对象, 消息转发结束.
  3. 消息签名 : 这里会要求你返回一个消息签名, 如果返回nil, 则消息转发结束.
  4. 完整的消息转发 : 备胎都搞不定了, 那就只能把该消息相关的所有细节都封装到一个NSInvocation对象, 再问接收者一次, 快想办法把这个搞定了. 到了这个地步如果还无法处理, 消息转发机制也无能为力了。

1. 动态方法解析

对象在收到无法解读的消息后, 首先调用其所属类的这个类方法 :

+ (BOOL)resolveInstanceMethod:(SEL)selector
// selector : 那个未知的选择子
// 返回YES则结束消息转发
// 返回NO则进入备胎

假如尚未实现的方法不是实例方法而是类方法, 则会调用另一个方法resolveClassMethod:

2. 备胎

动态方法解析失败, 则调用这个方法

- (id)forwardingTargetForSelector:(SEL)selector
// selector : 那个未知的消息
// 返回一个能响应该未知选择子的备胎对象

通过备胎这个方法, 可以用”组合”来模拟出”多重继承”.

3. 消息签名

备胎搞不定, 这个方法就准备要被包装成一个NSInvocation对象, 在这里要先返回一个方法签名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector // NSMethodSignature : 该selector对应的方法签名

4. 完整的消息转发

给接收者最后一次机会把这个方法处理了, 搞不定就直接程序崩溃!

- (void)forwardInvocation:(NSInvocation *)invocation
// invocation : 封装了与那条尚未处理的消息相关的所有细节的对象

在这里能做的比较现实的事就是 : 在触发消息前, 先以某种方式改变消息内容, 比如追加另外一个参数, 或是改变消息等等. 实现此方法时, 如果发现某调用操作不应该由本类处理, 可以调用超类的同名方法. 则继承体系中的每个类都有机会处理该请求, 直到NSObject. 如果NSObject搞不定, 则还会调用doesNotRecognizeSelector:来抛出异常, 此时你就会在控制台看到那熟悉的unrecognized selector sent to instance..

上面这4个方法均是模板方法,开发者可以override,由runtime来调用。最常见的实现消息转发,就是重写方法3和4,忽略这个消息或者代理给其他对象.

Runtime-消息发送和消息转发相关推荐

  1. 消息发送到消息接收的整体流程

    1. Producer将消息发送到Broker后,Broker会采用同步或者异步的方式把消息写入到CommitLog.RocketMQ所有的消息都会存放在CommitLog中,为了保证消息存储不发生混 ...

  2. linux网络通信命令-如何给其他用户发送消息发送全体消息

    1.who命令查看当前在线的用户 使用who命令查看当前在线的用户,并且可以看到用户的最后一次登录时间 2.wall命令发送全体广播 wall命令会将讯息传给每一个 mesg 设定为 yes 的上线使 ...

  3. kafka通过控制台模拟消息发送和消息接收正常,但是通过javaAPI操作生产者发送消息不成功 消费者接收不到数据解决方案?

    通过命令行工具(kafka-console-producer.sh和kafka-console-consumer.sh)是能够相互通信的,producer发布的信息consumer能够接收到. 但是j ...

  4. 计算发送延时与传播延迟_消息队列——延时消息应用解析及实践

    简介:在大部分场景下业务系统如果只需要实现异步解耦.削峰填谷等能力,常规的普通消息就可以满足此类需求.除此之外,在某些特殊的业务场景中,普通消息类型存在无法满足需求的情况.这就需要消息队列服务本身支持 ...

  5. 传感器信号 如何发送到服务器,传感器如何将消息发送给云服务器

    传感器如何将消息发送给云服务器 内容精选 换一换 消息发送和消费的可靠性必须由DMS服务和生产者以及消费者协同工作才能保证.同时开发者需要尽量合理使用DMS消息队列,以提高消息发送和消息消费的效率与准 ...

  6. Python发送微信消息(文字、图片、文件)给指定好友和微信群,零基础可看懂(附源码和教程)

    前言 本示例是调用Windows API模拟发送,用Python调用win32api这个库来调用Windows API模拟人的手动操作来发送消息. 在使用前,请将你微信的窗口设置为在最前面,这样就便于 ...

  7. Python发送微信消息(文字、图片、文件)给指定好友和微信群(调用Win32 API模拟人的手动操作来发送消息)

    本示例是调用Windows API模拟发送,用Python调用win32api这个库来调用Windows API模拟人的手动操作来发送消息. 在使用前,请将你微信的窗口设置为在最前面,这样就便于程序找 ...

  8. RocketMQ:Producer启动流程与消息发送源码分析

    文章目录 Producer 1.方法和属性 2.启动流程 3.消息发送 3.1验证消息 3.2查找路由 3.3选择队列 3.4发送消息 3.5发送批量消息 Producer 在RocketMQ中,消息 ...

  9. PHP+TP框架实现微信公众号开发之发送模板消息

    一:准备工作. 1.将需要使用到的微信配置放在config.php配置文件中方便获取.(我使用的是微信测试号) return array(//'配置项'=>'配置值''appID'=>'w ...

  10. springboot集成rabbitmq,根据查询的信息创建多个消息中心和消息队列,并实现不同的消息发送到不同的消息中心

    今天接到一个需求,就是在发送消息到rabbitmq消息中心的时候,需要根据设备类型,将消息发送到不同的消息队列,因此要创建不同的消息队列.       修改之前是把配置信息写在配置文中,项目启动时,获 ...

最新文章

  1. fiddler使用技巧进阶,如何抓包修改数据?——AutoResponder重定向
  2. 教你清楚了解JAVA动态代理
  3. 【mysql解决办法】insert into select 想插入的数据如果部分为空怎么办?
  4. Java程序员从笨鸟到菜鸟之(一百零九)一步一步学习webservice(三)开发第一个基于XFire的webservice
  5. LabVIEW设计模式系列——移位寄存器
  6. faster rcnn学习之rpn训练全过程
  7. Java——集合带All的功能演示
  8. 【配置属性】—Entity Framework实例详解
  9. Linux下MySQL server和client安装
  10. 和yupeng的讨论
  11. java基于jxl.jar包生成Excel文件到指定目录和服务器下载两种模式的使用方法
  12. ListView使用BaseAdapter与ListView的优化
  13. 修正的判定条件覆盖例题_硬核:嵌入式代码覆盖率统计方法和经验
  14. 如何写好一个UITableView
  15. FFmpeg的编解码(二)
  16. 日更第4期-2015-1-19-openFrameworks系列第三讲-面向对象的小球们
  17. 王建林的一个亿,靠打工能实现么?
  18. vdbench安装及使用
  19. 英语语法学习--名词
  20. Spring Cloud Gateway — 网关基本功能API暴露

热门文章

  1. Forward+ Shading架构
  2. JavaScript之如何对客户端进行检测
  3. careercup-C和C++ 13.2
  4. Linux下配置SSL (转)
  5. ext3grep practice record
  6. 第三章:Creating Utilities--24.一个交互式的计算器
  7. Fedora 从 15.0 开始将修改以太网卡命名规则
  8. Javascript 滑动效果菜单 TreeView [Javascript]
  9. 【转】做正确的事情,等着被开除(Do the right thing, Wait to get fired)
  10. 本地搭建Hadoop伪分布式环境之四:开启搭建Hadoop2.4.0之旅