消息转发原理浅析
2016-01-08 16:20
381 查看
消息:在iOS中调用方法就是向对象发送消息。
对于问题是如果没有这个方法调用,那么消息不就是发不了了?最经典的报错就是说不能识别一个实例的方法。
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[ViewController temBtnClick:]: unrecognized selector sent to instance 0x7b98c9a0’
分析:
方法在调用时,系统会查看这个对象能否接收到这个消息(前提是否有)。如果不能接收系统会默认采取一些方法(你只需要实现),给你补救的机会。 接下来的事情就是在这个补救过程中开展了。
方案一:动态方法解析(Dynamic Method Resolution或Lazy method resolution)
向当前类(
方案二:快速转发路径(Fast forwarding path)
若果当前
方案三:慢速转发路径(Normal forwarding path)
首先
其次如果有方法签名返回,
若
示例如下:
创建一个控制器创建一个button,并添加方法
参考:
http://blog.csdn.net/c395565746c/article/details/8507008 (比较全面深入)
http://www.cocoachina.com/ios/20150604/12013.html (比较易懂)
对于问题是如果没有这个方法调用,那么消息不就是发不了了?最经典的报错就是说不能识别一个实例的方法。
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[ViewController temBtnClick:]: unrecognized selector sent to instance 0x7b98c9a0’
分析:
方法在调用时,系统会查看这个对象能否接收到这个消息(前提是否有)。如果不能接收系统会默认采取一些方法(你只需要实现),给你补救的机会。 接下来的事情就是在这个补救过程中开展了。
方案一:动态方法解析(Dynamic Method Resolution或Lazy method resolution)
向当前类(
Class)发送
resolveInstanceMethod:(对于类方法则为
resolveClassMethod:)消息,如果返回
YES,则系统认为请求的方法已经加入到了,则会重新发送消息。
+ (BOOL)resolveInstanceMethod:(SEL)sel // 对象(实例) + (BOOL)resolveClassMethod:(SEL)sel // 类
方案二:快速转发路径(Fast forwarding path)
若果当前
target实现了
forwardingTargetForSelector:方法,则调用此方法。如果此方法返回除nil和self的其他对象,则向返回对象重新发送消息
- (id)forwardingTargetForSelector:(SEL)aSelector // 返回一个有所需要方法的对象
方案三:慢速转发路径(Normal forwarding path)
首先
runtime发送
methodSignatureForSelector:消息查看
Selector对应的方法签名,即参数与返回值的类型信息例:
(v@:@)。
其次如果有方法签名返回,
runtime则根据方法签名创建描述该消息的
NSInvocation,向当前对象发送
forwardInvocation:消息,以创建的
NSInvocation对象作为参数;
若
methodSignatureForSelector:无方法签名返回,则向当前对象发送
doesNotRecognizeSelector:消息,程序抛出异常退出。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; // 返回签名 - (void)forwardInvocation:(NSInvocation *)anInvocation; // 执行
示例如下:
创建一个控制器创建一个button,并添加方法
viewDidLoad: UIButton *temBtn = [UIButton buttonWithType:UIButtonTypeCustom]; temBtn.frame = CGRectMake(40, 100, 80, 40); [temBtn setTitle:@"测试" forState:UIControlStateNormal]; [temBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [temBtn addTarget:self action:@selector(temBtnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:temBtn];
#warning 假设没有实现 /* - (void)temBtnClick:(UIButton *)btn { NSLog(@"现在执行到这个方法"); } */ #warning 方案一 /** 描述: 向当前类(class)发送resolveInstanceMethod:(类方法则为resolveClassMethod:)消息,如果返回YES,则系统认为请求的方法已经加入到了,则会重新发送消息。 */ /* void click(id self,SEL _cmd,UIButton *btn) { NSLog(@"成功的解决了问题,%@",btn); } + (BOOL)resolveInstanceMethod:(SEL)sel { // 只能掌管一个类中的方法 if (sel == @selector(temBtnClick:)) { class_addMethod(self, sel, (IMP)click, "v@:@"); return YES; } return [super resolveInstanceMethod:sel]; } */ #warning 方案二 (快速转发路径 Fast forwarding path) /* - (id)forwardingTargetForSelector:(SEL)aSelector { NSLog(@"走到了这里"); // 需要创建一个Deal类,并实现temBtnClick:这个方法 return [[Deal alloc] init]; // 此实例拥有temBtnClick:这个方法可以处理 } */ #warning 方案三 (慢速转发路径 Normal forwarding path) - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { // 为方法生成方法签名,这个签名就是给下面的anInvocation调用的 invocation中有一个方法就是通过sig生成的 NSString *sel = NSStringFromSelector(aSelector); if ([sel isEqualToString:@"temBtnClick:"]) { NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:"v@:@"]; // 方法签名 return sig; } return [super methodSignatureForSelector:aSelector]; } - (void)forwardInvocation:(NSInvocation *)anInvocation { SEL selector = [anInvocation selector]; Deal *deal = [[Deal alloc] init]; if ([deal respondsToSelector:selector]) { [anInvocation invokeWithTarget:deal]; } }
参考:
http://blog.csdn.net/c395565746c/article/details/8507008 (比较全面深入)
http://www.cocoachina.com/ios/20150604/12013.html (比较易懂)
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 讲解iOS开发中基本的定位功能实现
- js判断客户端是iOS还是Android等移动终端的方法
- IOS开发环境windows化攻略
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- .net平台推送ios消息的实现方法
- 探讨Android与iOS,我们将何去何从?
- Android、iOS和Windows Phone中的推送技术详解
- IOS 改变键盘颜色代码
- 举例详解iOS开发过程中的沙盒机制与文件
- Android和IOS的浏览器中检测是否安装某个客户端的方法
- 分享一个iOS下实现基本绘画板功能的简单方法
- javascript实现阻止iOS APP中的链接打开Safari浏览器