iOS Runtime的消息转发机制
前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!!
Runtime基本概念:https://www.cnblogs.com/guohai-stronger/p/9154889.html
Runtime基本使用:https://www.cnblogs.com/guohai-stronger/p/9184356.html
看过上面两篇博客之后,大家可能会对Runtime有所了解,但在上述讲述Runtime还有一个问题,当对象无法接收到相关的消息时候,又会发生什么?这就是我们即将讲的消息转发机制。
一、前言
在讲述消息转发机制前,先通过一个简单的例子
id num = @;
//输出123
NSLog(@"%@", num);
//程序崩溃,报错[__NSCFNumber appendString:]: unrecognized selector sent to instance 0x7b27
[num appendString:@"Hello World"];
在程序代码中加入上面代码,运行过程为:先在相关的类中,搜索方法列表,如果出现找不到则会一直向上搜索到根部(也就是NSObject);如果出现还找不到并且消息转发都失败,此时就会执行doesNotRecognizeSelector:紧接着方法报unrecognized selector错误?
下面我们来讲述消息转发的过程中,为什么经常出现消息的最后三次机会?
第一步:所属类的动态方法解析
首先,如果沿着继承树没有搜索到相关的方法时,则就会向接受者所属的类进行一次请求,看是否可以动态的添加一个方法,如下:
+(BOOL)resolveInstanceMethod:(SEL)name
注意这是一个类方法,因为向接受者所属的类进行一次请求。
下面我们举个例子:
#import "ViewController.h"
#import <objc/runtime.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Runtime";
[self performSelector:@selector(dynamicSelector) withObject:nil];
} + (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(dynamicSelector)) {
class_addMethod([self class],sel, (IMP)myMehtod,"v@:");
return YES;
}else{
return [super resolveInstanceMethod:sel];
} } void myMehtod(id self,SEL _cmd){
NSLog(@"This is added dynamic");
}
在看结果之前,我们先简单了解下:class_addMethod(上面出现的)
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
此函数共有四个参数:
- Class cls:要添加的类对象
- name:添加后的selector方法名字
- imp:实现方法
- type:方法参数的编码
方法的返回值为BOOL类型:YES表示本类可以处理;NO代表需要使用转发机制。
下面是上面的运行结果,结果如下:

如果第一步不能处理,会进行到第二步。
第二步:调用forwardingTargetForSelector把任务转发给另一个对象。
#import "ViewController.h"
#import <objc/runtime.h> @interface CustomObject : NSObject
-(void)dynamicSelector;
@end
@implementation CustomObject -(void)dynamicSelector{
NSLog(@"hello world");
}
@end @interface ViewController ()
@property (strong,nonatomic)CustomObject * myObj;
@end
@implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
self.myObj = [[CustomObject alloc] init];
[self performSelector:@selector(dynamicSelector) withObject:nil]; } -(id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(dynamicSelector) && [self.myObj respondsToSelector:@selector(dynamicSelector)]) {
return self.myObj;
}else{
return [super forwardingTargetForSelector:aSelector];
} }
@end
如果第二步骤也不能处理的时候,会交给第三步骤。
第三步:调用forwardInvocation转发给其他
#import "ViewController.h"
#import <objc/runtime.h> @interface CustomObject : NSObject
-(void)dynamicSelector;
@end
@implementation CustomObject -(void)dynamicSelector{
NSLog(@"hello world");
}
@end
@interface ViewController ()
@property (strong,nonatomic)CustomObject * myObj;
@end
@implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
self.myObj = [[CustomObject alloc] init];
[self performSelector:@selector(dynamicSelector) withObject:nil]; }
-(void)forwardInvocation:(NSInvocation *)anInvocation{
if ([self.myObj respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:self.myObj];
}else{
[super forwardInvocation:anInvocation];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [CustomObject instanceMethodSignatureForSelector:aSelector];
}
@end
上面就是iOS Runtime消息的转发机制,欢迎指正!!!
iOS Runtime的消息转发机制的更多相关文章
- OC:浅析Runtime中消息转发机制
一.介绍 OC是一门动态性语言,其实现的本质是利用runtime机制.在runtime中,对象调用方法,其实就是给对象发送一个消息,也即objc_msgSend().在这个消息发送的过程中,系统会进行 ...
- iOS的消息转发机制详解
iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...
- iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制
你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...
- iOS 消息转发机制
这篇博客的前置知识点是 OC 的消息传递机制,如果你对此还不了解,请先学习之,再来看这篇.这篇博客我尝试用口语的方式像讲述 PPT 一样给大家讲述这个知识点. 我们来思考一个问题,如果对象在收到无法解 ...
- iOS消息转发机制
iOS消息转发机制 “消息派发系统”(message-dispatch system) 若想令类能够理解某条消息,我们必须实现出对应的方法才行.但是,在编译器向类发送其无法解读的消息时并不会报错,因为 ...
- 理解Objective-C Runtime(三)消息转发机制
消息转发机制概述 上一篇博客消息传递机制中讲解了Objective-C中对象的「消息传递机制」.本文需要讲解另外一个重要问题:当对象受到无法处理的消息之后会发生什么情况? 显然,若想令类能理解某条消息 ...
- runtime之消息转发
前言 在上一篇文章中我们初尝了runtime的黑魔法,可以在程序编译阶段就获取到成员变量的名字,特性以及动态的给对象增加属性等等,在接下来中我们进一步了解OC的消息发送机制.如果之前没接触过runti ...
- Effective Objective-C 2.0 — 第12条:理解消息转发机制
11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. ...
- runtime消息转发机制
Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制.而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库.它是 Objective- ...
随机推荐
- 画线代码V1.0.0
画线代码: 最终效果图: 优点: 1.效果还行,计算量也不大(就一点2维直线一般式能有多少运算量). 缺点: 1.每条线怎么也是建模,可能会有点开销. 2.编辑起来很是麻烦. 代码部分: /***** ...
- Python中用random产生随机数的用法
>>>random.randomrandom.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0 >>>random.unifo ...
- spring boot 入门及示例
需要环境:eclipse4.7.3 + jdk1.8 +maven3.6.1 + tomcat(web需要) spring boot官网介绍:https://spring.io/guides/gs/s ...
- 关于iOS与html交互,隐藏或修改html标签内容
wkwebview 1.隐藏顶部标题栏 [webView evaluateJavaScript:@"document.getElementsByClassName('page-header' ...
- Java语言中的面向对象特性
面向对象的基本特征 1.封装性 封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义: ◇ 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位( ...
- 一次非常有趣的 SQL 优化经历
阅读本文大概需要 6 分钟. 前言 在网上刷到一篇数据库优化的文章,自己也来研究一波. 场景 数据库版本:5.7.25 ,运行在虚拟机中. 课程表 #课程表 create table Course( ...
- GIT学习笔记——常用命令
最近使用使用GIT较多,但命令很容易就忘记了,于是整理下,大多整理与一些文档和他人博客 在当前目录新建建一个纯git代码库 $ git --bare init 在当前目录新建一个Git代码库 $ gi ...
- MySQL-8.0.11 在 Windows10 上的安装
下载 MySQL8.0 For Windows zip包下载地址:https://dev.mysql.com/downloads/file/?id=476233. 进入页面后可以不登录,点击底部“No ...
- 第76节:Java中的基础知识
第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...
- 解决微信小程序使用wxcharts在屏幕不固定问题-开发工具里也显示好了布局,为啥到真机就是乱的
解决微信小程序使用wxcharts在屏幕不固定问题-开发工具里也显示好了布局,为啥到真机就是乱的 .chart{ width: 100%; text-align: center; } .canvas{ ...