Runtime消息动态解析与转发流程

先上图:

 

下面根据具体代码看这张图。

一、创建一个Person类,

 Person.h

#import <Foundation/Foundation.h>@interface Person : NSObject-(void)sendMessage:(NSString *)message;@end

Person.m

#import "Person.h"
#import <objc/runtime.h>@implementation Person@end

大家可以看到,Person类只声明了 sendMessage:方法,在.m文件里没有实现这个方法。

 

这时,如果在viewController中调用Person类的sendMessage方法,程序会发生崩溃。

#import "ViewController.h"
#import "Person.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];[[[Person alloc]init] sendMessage:@"Hello"];}

 

 

结合上面的图片,我们说说消息处理的机制。

1.当我们调用的方法没有具体的实现时,会调用

+ (BOOL)resolveInstanceMethod:(SEL)sel;

+(BOOL)resolveInstanceMethod:(SEL)sel{NSString *methodName = NSStringFromSelector(sel);if ([methodName isEqualToString:@"sendMessage:"]) {//我们可以在这里添加方法的实现return class_addMethod(self, sel, (IMP)sendMessage, "v@:@");}return NO;}void sendMessage (id self, SEL _cmd, NSString *message){NSLog(@"message=%@",message);
}

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types):为类动态添加方法。如果有同名会返回NO,成功返回YES。

其中的参数types查询地址:(v:表示void, @:表示类型,等等)

 

2. 如果 resolveInstanceMethod:方法返回NO,调用

-(id)forwardingTargetForSelector:(SEL)aSelector;

这个方法是找备用者,比如:Animal类。

Animal.h

#import <Foundation/Foundation.h>@interface Animal : NSObject@end

Animal.m

#import "Animal.h"@implementation Animal-(void)sendMessage:(NSString *)message{NSLog(@"message=%@",message);
}@end

Animal类没有声明sendMessage:方法,但在.m文件里有这个方法的实现,可以作为备用者。如下:

-(id)forwardingTargetForSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);if ([methodName isEqualToString:@"sendMessage:"]) {if ([[Animal new] respondsToSelector:aSelector]) {return [Animal new];}}return [super forwardingTargetForSelector:aSelector];
}

3. 如果 forwardingTargetForSelector:(SEL)aSelector返回 nil。

// 若前两种方法都不处理,则走这里
//    1)方法签名
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);if ([methodName isEqualToString:@"sendMessage:"]) {return [NSMethodSignature signatureWithObjCTypes:"v@:@"];}return [super methodSignatureForSelector:aSelector];
}
//  2) 签名后,消息转发,找备用者
-(void)forwardInvocation:(NSInvocation *)anInvocation{SEL selector = [anInvocation selector];Animal *animal = [Animal new];if ([animal respondsToSelector:selector]) {[anInvocation invokeWithTarget:animal];} else{[super forwardInvocation:anInvocation];}
}

 

4.如果走到第3步,仍然不做处理,如下:

-(void)forwardInvocation:(NSInvocation *)anInvocation{[super forwardInvocation:anInvocation];
}

这时为了程序的健壮性,防止崩溃,可以用以下方法处理。

//  若前3方法都不处理,为了防止崩溃,可调用此方法
-(void)doesNotRecognizeSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);NSLog(@"找不到 %@ 这个方法的实现",methodName);
}

 

附加源码

转载于:https://www.cnblogs.com/lfyDragon/p/9177710.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465725.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

编写优美的GTest测试案例

使用gtest也有很长一段时间了&#xff0c;这期间也积累了一些经验&#xff0c;所以分享一下。GTest为我们提供了便捷的测试框架&#xff0c;让我们只需要关注案例本身。如何在GTest框架下写出优美的测试案例&#xff0c;我觉得必须要做到&#xff1a; 案例的层次结构一定要清晰…

评分9.3,你想要的那本书,来了!

还记得那天晚上我发的朋友圈吗&#xff1f;经过不完全统计&#xff0c;更多的人喜欢C语言这本书&#xff0c;所以这次先安排抽奖这本书籍&#xff0c;属于出版社赞助&#xff0c;也是给大家一个获奖的机会。不吹牛啊&#xff0c;我们办公室一个大神&#xff0c;写算法的&#x…

Python3安装(Linux)

Linux下Python3环境搭建 目录 Linux下Python3环境搭建 检查Python版本&#xff08;ubuntu16.04&#xff09; Helloworld IDE —— Geany 检查Python版本&#xff08;ubuntu16.04&#xff09; Linux默认已经安装了Python。CtrlAltT调出终端&#xff0c;输入python&#xff…

create-react-app 创建react项目 多页面应用

1:npm install -g create-react-app 2:创建一个应用 create-react-app my-app cd my-app 3:提取配置文件 npm run eject 4:允许文件 npm start create-react-app 默认是创建单页面应用&#xff0c;但是也可以创建多页面应用&#xff0c;需要手动配置一下webpack 第一步&…

c语言指针用法详解,通俗易懂超详细!

文章转自&#xff1a;无际单片机大家好&#xff0c;我是无际。今天给大家来讲解一下指针。我会由浅到深&#xff0c;最后结合实际应用讲解&#xff0c;让大家学会指针的同时&#xff0c;知道大佬们都用指针来干嘛&#xff01;长文预警&#xff01;全文大约5200多字&#xff0c;…

Python3 —— 变量和简单数据类型

Python3 —— 变量和简单数据类型 目录 python3 —— 变量和简单数据类型 一、变量 1、变量&#xff08;每个变量都存储了一个值——与变量相关联的信息&#xff09; 2、变量命名 二、简单数据类型&#xff08;整型&#xff0c;浮点型&#xff0c;字符串等&#xff09; 1…

Linux C Socket编程,这篇文章让我耳目一新

目录1. 什么是TCP/IP、UDP&#xff1f;2. Socket在哪里呢&#xff1f;3. Socket是什么呢&#xff1f;4. 有很多的框架&#xff0c;为什么还在从Socket开始&#xff1f;5. Linux C Socket简单示例1.什么是TCP/IP、UDP&#xff1f;TCP/IP&#xff08;Transmission Cont…

视频下载比想象中容易

两周前搞定了56.com的视频独立播放和视频下载后&#xff0c;很得意是吹嘘了一把&#xff0c;有一些朋友也就试着用了&#xff08;有朋友笑称我在为56.com做广告&#xff0c;因为他以前是不知道56.com的&#xff0c;我这么一搞&#xff0c;他竟也喜欢上56.com看视频了&#xff0…

微处理器:50岁了!

编排 | strongerHuang微信公众号 | 嵌入式专栏50年前&#xff08;1971年&#xff09;&#xff0c;英特尔推出了第一款商用的通用型微处理器 4004&#xff0c;4004拥有2300多个晶体管&#xff0c;与当今芯片中的几十上百亿个晶体管相比&#xff0c;这个数字相形见绌&#xff0c;…

Python3 —— 列表

Python3 —— 列表 目录 Python3 —— 列表 1.访问列表元素&#xff08;索引&#xff09; 2.修改列表元素 3.添加列表元素 4.删除列表元素 5.组织列表 6.遍历整个列表&#xff08;for循环&#xff0c;缩进部分都在for范围之内&#xff09; 7.创建数值列表 8.列表简单…

当卷烟厂也那么卷后……

过年回家&#xff0c;跟几个同学一起吃饭&#xff0c;聊到当时班上读书厉害的一个同学。同学嘴巴瞪得很大&#xff0c;说了一句&#xff0c;他在烟厂企业上班&#xff0c;现在开的什么什么车&#xff0c;待遇好得不得了。中学时候&#xff0c;那个同学读书真的厉害&#xff0c;…

Python3 —— if/while/input

Python3 —— if/while/input 目录 Python3 —— if/while/input 1.条件测试 2.if语句 3.input()函数 4.while循环 5.break与continue 1.条件测试 等于 ! 不等于 < 小于 < 小于等于 > 大于 > 大于等于 and 与 or 或 not in 不在 2…

python 全栈开发,Day63(子查询,MySQl创建用户和授权,可视化工具Navicat的使用,pymysql模块的使用)...

昨日内容回顾 外键的变种三种关系&#xff1a;多对一&#xff1a;左表的多 对右表一 成立左边的一 对右表多 不成立foreign key(从表的id) refreences 主表的&#xff08;id&#xff09;多对多建立第三张表&#xff08;foreign key&#xff09;一对一foreign keyunique单表查询…

我偶尔会用到的调试方法 | Linux 内核

文章转自我朋友的公众号&#xff0c;以下为内容正文大家好&#xff0c;我是你们的工具人老吴。今天,和大家分享一下几个 Linux 内核的调试小技巧。当你遇到一个 bug&#xff0c;你调试了 1 年半载都解决不了&#xff0c;这其实一件好事。因为它会时刻提醒你平时写代码时要谨慎、…

Linux应用编程之共享内存实例

1共享内存实例01主要内容 上一小节小哥跟大家介绍了一下共享内存的知识&#xff0c;今天主要是做一个实战的演示&#xff0c;从而更好的理解共享内存的原理和实际应用。02程序示例 1#include <stdlib.h>2#include <stdio.h>3#include <string.h>4#inclu…

洛谷P1279 字串距离 (动态规划)

题目描述 设有字符串X&#xff0c;我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串&#xff0c;如字符串X为”abcbcd”&#xff0c;则字符串“abcb□cd”&#xff0c;“□a□bcbcd□”和“abcb□cd□”都是X的扩展串&#xff0c;这里“□”代表空格字符。 如…

Python3——函数

Python3——函数 目录 Python3——函数 定义函数 实参和形参 返回值 将函数存储在模块中 定义函数 关键字def告知Python要定义一个函数。 最后一行是调用此函数&#xff0c;此函数不带参数和返回值。 实参和形参 函数参数可以有一个或者多个&#xff0c;可以是简单数据…

ASP.NET MVC 整合 Spring.net(1)- Controller进容器

我们都知道Asp.net MVC自有一套执行机制。通过分析MVC的MvcHandler关键代码ProcessRequest protectedinternalvirtualvoidProcessRequest(HttpContextBase httpContext) { AddVersionHeader(httpContext); //Get the controller typestringcontrollerNam…

再读王垠的《编程的智慧》,有怎样的感想?

王垠老师的《编程的智慧》这篇文章已经读了最起码5遍了&#xff0c;最近的项目做完一个阶段&#xff0c;到了把他做干净的时候&#xff0c;也就是优化代码&#xff0c;全面整理的阶段&#xff0c;这个时候我又想起了这篇编程的智慧&#xff0c;有一些启发与大家分享。王垠老师的…

国外流行的五款免费在线图片编辑器评测

也许当你在度假的时候&#xff0c;不喜欢携带着你的笔记本电脑&#xff0c;但你在度假的时候一定会拍照。现在&#xff0c;你可以打理这些照片&#xff0c;甚至还可以在“网络咖啡屋”中进行一些高级的图像编辑。一些基于网络的照片编辑程序在去年逐渐兴起&#xff0c;大多是基…