博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 消息转发
阅读量:7078 次
发布时间:2019-06-28

本文共 2092 字,大约阅读时间需要 6 分钟。

消息转发  
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.    
  3. @end   
 
  1. @interface Doctor : NSObject   
  2.    
  3. - (void)operate;   
  4. @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.    
  4. @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.        
  11.     return signature;   
  12. }   
  13.    
  14. - (void)forwardInvocation:(NSInvocation *)anInvocation   
  15. {   
  16.     SEL seletor = [anInvocation selector];   
  17.     if ([someObj respondsToSelector:seletor]) {   
  18.         [anInvocation invokeWithTarget:someObj];   
  19.     }   
  20.        
  21. }   
两种消息转发方式的比较
    
快速消息转发:简单、快速、但仅能转发给一个对象。
标准消息转发:稍复杂、较慢、但转发操作实现可控,可以实现多对象转发。

转载地址:http://zjpml.baihongyu.com/

你可能感兴趣的文章
render httprequest
查看>>
lsattr, chattr
查看>>
redis key设置过期时间
查看>>
0514JS基础:操作document对象、事件、this
查看>>
Gtest:源码解析
查看>>
【杂题总汇】HDU2018多校赛第九场 Rikka with Nash Equilibrium
查看>>
获取FIle路径下所有文件的地址和名称
查看>>
11.HTML表单元素【中】
查看>>
浙大版《C语言程序设计(第3版)》题目集 练习3-4 统计字符 (15 分)
查看>>
oracle创建计划任务
查看>>
16进制转10进制
查看>>
windows 安装服务
查看>>
MySQL常用简单小命令
查看>>
ERROR: child process failed, exited with error number 100 mongodb报错
查看>>
epoll 使用小结
查看>>
基于TCP套接字实现的简单Demo
查看>>
OpenStack学习
查看>>
LeetCode OJ - Longest Consecutive Sequence
查看>>
柯南剧场版17绝海的侦探
查看>>
20个响应式网页设计中的“神话”误区
查看>>