消息转发  
delegate和protocol  
类别   
 
消息转发
 
当向someObject发送某消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runtime system并不会立即报错使程序崩溃,而是依次执行下列步骤:
 
分别简述一下流程:
    
1.动态方法解析:向当前类发送 resolveInstanceMethod: 信号,检查是否动态向该类添加了方法。(迷茫请搜索:@dynamic)
2.快速消息转发:检查该类是否实现了 forwardingTargetForSelector: 方法,若实现了则调用这个方法。若该方法返回值对象非nil或非self,则向该返回对象重新发送消息。
3.标准消息转发:runtime发送methodSignatureForSelector:消息获取Selector对应的方法签名。返回值非空则通过forwardInvocation:转发消息,返回值为空则向当前对象发送doesNotRecognizeSelector:消息,程序崩溃退出。
 
顾名思义,我们可以利用上述过程中的2、3两种方式来完成消息转发。
 
快速消息转发
     
快速消息转发的实现方法很简单,只需要重写 - (id)forwardingTargetForSelector:(SEL)aSelector  方法即可。
我来举个简单的例子,比如现有2个类:Teacher 和 Doctor,Doctor可以做手术(operate方法)。
 
  1. @interface Teacher : NSObject
  2. @end
 
  1. @interface Doctor : NSObject
  2. - (void)operate;
  3. @end
通过快速消息转发,可以很轻松的让teacher调用doctor的方法做手术。
    
Teacher类需要实现将消息转发给Doctor:
 
  1. - (id)forwardingTargetForSelector:(SEL)aSelector
  2. {
  3. Doctor *doctor = [[Doctor alloc]init];
  4. if ([doctor respondsToSelector:aSelector]) {
  5. return doctor;
  6. }
  7. return nil;
  8. }
虽然消息可以动态转发传递,但是编辑器的静态检查是绕不过的,那么问题来了,既然Teacher类没有实现operate方法又该如何声明呢?
到目前为止,我只想到下面2种方法:
    
声明方法1 ———— 类别
 
  1. @interface Teacher (DoctorMethod)
  2. - (void)operate;
  3. @end
 
声明方法2 ———— 导入头文件、调用时强转类型
 
Teacher类头文件需要包含Doctor头文件,告诉编译器去Doctor.h中可以找到operator方法的声明,并且在调用时强转类型。
 
  1. Teacher *teacher = [[Teacher alloc]init];
  2. [(Doctor *)teacher operate];
有兴趣可以思考一个问题:如果将其类型转成 id ,也可以编译通过,并实现转发。可是会带来什么隐患呢?
    
方法1使用类别足够清晰简便,为什么还要提出办法2呢 ? 我的想法是,方法1的弊端是抛出来的方法是定死的,而且在.h里露着;方法2就相对灵活,而且隐藏了我要转发的消息。
   
    
标准消息转发
标准消息转发需要重写 methodSignatureForSelector: 和 forwardInvocation: 两个方法即可。
发流程如图所示:
 
转发重写方法:
 
  1. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
  2. {
  3. NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
  4. if (signature==nil) {
  5. signature = [someObj methodSignatureForSelector:aSelector];
  6. }
  7. NSUInteger argCount = [signature numberOfArguments];
  8. for (NSInteger i=0 ; i<argCount ; i++) {
  9. }
  10. return signature;
  11. }
  12. - (void)forwardInvocation:(NSInvocation *)anInvocation
  13. {
  14. SEL seletor = [anInvocation selector];
  15. if ([someObj respondsToSelector:seletor]) {
  16. [anInvocation invokeWithTarget:someObj];
  17. }
  18. }
两种消息转发方式的比较
    
快速消息转发:简单、快速、但仅能转发给一个对象。
标准消息转发:稍复杂、较慢、但转发操作实现可控,可以实现多对象转发。

iOS 消息转发的更多相关文章

  1. iOS消息转发机制

    iOS消息转发机制 “消息派发系统”(message-dispatch system) 若想令类能够理解某条消息,我们必须实现出对应的方法才行.但是,在编译器向类发送其无法解读的消息时并不会报错,因为 ...

  2. iOS 消息转发机制

    这篇博客的前置知识点是 OC 的消息传递机制,如果你对此还不了解,请先学习之,再来看这篇.这篇博客我尝试用口语的方式像讲述 PPT 一样给大家讲述这个知识点. 我们来思考一个问题,如果对象在收到无法解 ...

  3. iOS 消息转发以及 NSProxy 实战

    最后更新: 2018-01-17 一.消息派发机制-NSObject 在 iOS 开发中, 调用对象的方法就是给对象发送一个消息.了解消息的派发机制对于iOS开发来说是一个很实用且强大的工具, 下面我 ...

  4. iOS消息转发

    消息转发是一种功能强大的技术,可以大大增加Objective-C的表现力.什么是消息转发?简而言之,它允许未知的消息被困住并作出反应.换句话说,无论何时发送未知消息,它​​都会以一个很好的包发送到您的 ...

  5. iOS - 消息转发处理

    详细运行时基础 NSInvocation介绍 NSHipster-Swizzling Objective-C Method相关方法分析 Type Encodings Objc是OOP,所以有多态. 当 ...

  6. ios 消息转发初探

    有时候服务器的接口文档上一个数据写的是string类型,这时候你就会直接把它赋值给一个label. 问题来了,有时候这个string的确是string,没有问题,有时候又是NSNumber,当然不管三 ...

  7. iOS的消息转发机制详解

    iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...

  8. iOS 消息发送与转发详解

    Objective-C 是一门动态语言,它将很多静态语言在编译和链接时期做的事情,放到了运行时来处理.之所以能具备这种特性,离不开 Runtime 这个库.Runtime 很好的解决了如何在运行时期找 ...

  9. iOS Runtime的消息转发机制

    前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!! Runtime基本概念:https://www.cn ...

随机推荐

  1. 快速排序QuickSort

    前几天实现了直接插入排序.冒泡排序和直接选择排序这三个基础排序.今天看了一下冒泡排序的改进算法,快速排序.单独记录一下,后面还有归并和基数排序等 快速排序 1.选择一个支点默认为数组第一个元素及arr ...

  2. algorithm之改变序列算法--待解决

    简述:改变序列算法,参见http://www.cplusplus.com/reference/algorithm/?kw=algorithm 待解决问题:iterator_traits.std::mo ...

  3. chart.js图表库案例赏析,饼图添加文字

    chart.js图表库案例赏析,饼图添加文字 Chart.js 是一个令人印象深刻的 JavaScript 图表库,建立在 HTML5 Canvas 基础上.目前,它支持6种图表类型(折线图,条形图, ...

  4. Socket的双网卡收发(C#)

    最近的一个项目中需要同时使用两块网卡收发UDP组播数据包,并且要求使用Socket的方式接收和发送网络数据包(我不会告诉你们我之前是直接使用SharpPcap来实现的).在C#中Socket接触的比较 ...

  5. 【BZOJ】【1020】【SHOI2008】安全的航线flight

    计算几何/二分/迭代/搜索+剪枝 写三个tag可能是因为从哪个方向来理解都可以吧…… 我完全不会计算几何所以抄了ydc的代码 题解:http://ydcydcy1.blog.163.com/blog/ ...

  6. 响应式设计Responsinator工具推荐

    from:http://www.25xt.com/allcode/4066.html 原文推荐了5种,感觉有用的吧就这一种,所以收藏过来. Responsinator工具的好处Responsinato ...

  7. ios 调用打印机

    源码 无意中玩一个demo发现调用了打印机  才发现ios有快速调用打印机的功能. if ([UIPrintInteractionController isPrintingAvailable] == ...

  8. [工作积累] android 中添加libssl和libcurl

    1. libssl https://github.com/guardianproject/openssl-android 然后执行ndk-build 2.libcurl 源代码组织结构, 下面的mak ...

  9. iis express 启动多个网站

      iis express一次只能运行一个网站,  执行iisexpress 不加参数. 将执行配置文件中的第一个网站. iis express一次只能运行一个 应用程序池. 可以使用这个特点实现一次 ...

  10. 快速、直接的XSS漏洞检测爬虫 – XSScrapy

    XSScrapy是一个快速.直接的XSS漏洞检测爬虫,你只需要一个URL,它便可以帮助你发现XSS跨站脚本漏洞. XSScrapy的XSS漏洞攻击测试向量将会覆盖 Http头中的Referer字段 U ...