runtime 容错机制一:消息的决议和转发
来源:互联网 发布:极简主义 知乎 编辑:程序博客网 时间:2024/05/17 19:17
在代码中,调用了一个声明但是未被实现的方法的时候(包括定义一个btn的点击事件,但是未实现),程序会奔溃,控制台提示:unrecognized selector sent to instance 'xxxxxxxxx'.
解决方案:利用runtime的消息机制。
定义一个testModel。
testModel.h中声明一个方法
@interface testModel : NSObject- (NSString *)testModel:(NSString *)txt;//- (void)testSecondModel;@end
testModel.m中
可以分为3步走:
1. 动态方法决议。objc运行时会调用
+ (BOOL)resolveInstanceMethod:(SEL)sel;//调用对象方法执行
+ (BOOL)resolveClassMethod:(SEL)sel;//调用类方法执行
让程序提供一个(本类中的函数)函数实现。如果你返回的是YES,运行时系统就会被重新启动一次消息发送的过程,如果返回的是NO,运行时会执行下一步,即消息转发(Message Forwording)。
CODE:
void testTest(id self,SEL _cmd) { NSLog(@"自动替换成了这个方法的实现");}@implementation testModel- (instancetype)init { if (self = [super init]) { } return self;}+ (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(testModel:)) { class_addMethod([self class], sel, (IMP)testTest, "v@:");//"v@:"看后面的注解 return true; } return [super resolveInstanceMethod:sel];}+ (BOOL)resolveClassMethod:(SEL)sel { return [super resolveClassMethod:sel];}当运行时根据方法名从当前类和父类中找不到方法的实现的时候,会执行决议方法,通过class_addMethod手动调用一个函数实现,从而避免crash。
2.如果动态决议未实现或者return NO,那么进入消息转发 Fast Forwording。
在目标类中实现
- (id)forwardingTargetForSelector:(SEL)aSelector;这个方法是可以把消息转发给另外其他对象,运行时会根据方法名去另外对象的方法列表中查找对应方法的实现。注意:调用这个方法的返回值不能是self或者nil,一般是其他的对象。
创建另外一个testSecondModel类:
不用在.h中声明,直接在.m中实现
#import "testSecondModel.h"@implementation testSecondModel- (NSString *)testModel:(NSString *)txt { return @"1234";}@end这样,方法的实现就被转移到了testSecondModel中来。
3. 最后一步,Normal forwording。
这一步是runtime最后一次挽救的机会,首先他会发送-methodSignatureForSelector:消息的函数的参数和返回值类型,如果-methodSignatureForSelector:返回nil,runtime则会发出-doesNotRecognizeSelector:消息,程序这个时候就奔溃了。如果返回了一个函数签名,runtime就会创建一个NSInvocation对象并发送-forwardingInvocation:消息给目标对象。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;获得函数的参数和返回值类型,如果返回nil,runtime则会发出:
- (void)doesNotRecognizeSelector:(SEL)aSelector;//抛出异常,程序Crash。理论上可以重写该方法避免程序奔溃,但是不建议这样做。如果不是返回的nil,而是一个函数签名,runtime就会创建一个NSInvocation并发送:
- (void)forwardInvocation:(NSInvocation *)invocation;在这个函数里把消息传递给其他对象。
CODE:- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSString *sel = NSStringFromSelector(aSelector); if (sel) { return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } return [super methodSignatureForSelector:aSelector];}- (void)forwardInvocation:(NSInvocation *)invocation { //拿到函数名 NSString *key = NSStringFromSelector([invocation selector]); if (key) { testSecondModel *second = [[testSecondModel alloc]init]; [invocation invokeWithTarget:second]; }}注释:
void testTest(id self,SEL _cmd) { }"v@:" 代表的是函数的返回类型void。
v : 函数的返回值
@: 参数
::方法
int say(id self, SEL _cmd, NSString *str) { }"i@:@"
i :代表函数的返回类型Int
@:代表函数的参数id self
::代表函数的方法 SEL _cmd
@:代表函数的参数 NSString *str;
- runtime 容错机制一:消息的决议和转发
- runTime 的消息转发机制
- Runtime消息转发机制
- Runtime消息转发机制
- 动态方法决议 和 消息转发
- 通过Runtime探讨iOS的消息转发机制
- iOS runtime学习之消息转发机制
- ios runtime IMP指针 消息转发机制
- iOS Runtime与消息转发机制
- Runtime 和消息机制
- runtime总结二之消息机制(包括消息转发,消息交换的黑魔法)
- cocoa动态方法决议及消息转发
- 动态方法决议与消息转发
- Runtime的消息机制
- runtime的消息机制
- OC学习Runtime之消息传递,消息转发机制
- runtime选择器和消息转发处理
- runtime浅谈(一)动态运行时和消息机制
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 H
- 149_IO_字节流_节点流_文件夹拷贝_工具制作_文件后缀与软件的关系
- 华为笔试题(8)
- 137. Single Number II
- 什么是P问题、NP问题和NPC问题
- runtime 容错机制一:消息的决议和转发
- 访问https,抛出的异常javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
- Oracle的简介
- LinkedList 双向链表
- 150_IO_字节流_节点流_拷贝_工具健壮性
- Java实训课3
- 二叉树的遍历
- 151_IO_字符流_纯文本_节点流_Reader_FileReader_Writer_FileWriter_读取_写出_拷贝
- cuda相关