cocoa动态方法决议及消息转发
假设给一个对象发送不能响应的消息,同一时候又没有进行动态方法决议,又没实现消息转发,那么就会引发以下的crash信息
2014-07-30 15:47:54.434 MethodNotFind[1719:403] -[Person setName:]: unrecognized selector sent to instance 0x100121db0
下面是測试的demo
先看看Person类的定义。
#import <Foundation/Foundation.h>
@class Car;
@interface Person : NSObject
{
Car* car; //用来处理不能转发的消息
} @property (copy)NSString* name; - (void)forwardInvocation:(NSInvocation *)anInvocation; -(void)print;
@end
Person.m的实现部分
#import "Person.h"
#import "Car.h"
@implementation Person @dynamic name; //两个作用:告诉编译器不要创建该属性的get和setter方法.告诉编译器不要创建实现属性所用的实例变量 //@synthesize name=myName; //告诉编译器在Person这个类里面帮我们创建get和set方法,同一时候为我们得Person类创建一个成员变量叫myName -(id)init
{
if (self=[super init]) {
car=[[Car alloc] init];
}
return self;
} -(void)dealloc
{
if (car)
{
[car release];
car=nil;
}
[super dealloc];
} void dynamicMethodIMP(id self, SEL _cmd)
{
// implementation ....
NSLog(@"动态决议方法被调用"); } + (BOOL)resolveInstanceMethod:(SEL)sel
{
NSLog(@"sel is %@", NSStringFromSelector(sel)); //得到方法名
if(sel == @selector(setName:)){
class_addMethod([self class],sel,(IMP)dynamicMethodIMP,"v@:");
return YES;
} return [super resolveInstanceMethod:sel];
} // 这种方法触发的前提就是+ (BOOL)resolveInstanceMethod:(SEL)返回NO,否则将不会进行触发。 子类重写这种方法,能够把消息转给一个指定得对象。还有必需要重写- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector这种方法.两个条件缺一不可 //注意:To respond to methods that your object does not itself recognize, you must override methodSignatureForSelector: in addition to forwardInvocation:. The mechanism for forwarding messages uses information obtained from methodSignatureForSelector: to create the NSInvocation object to be forwarded. Your overriding method must provide an appropriate method signature for the given selector, either by pre formulating one or by asking another object for one.
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL name =[anInvocation selector]; NSLog(@" >> forwardInvocation for selector %@", NSStringFromSelector(name));
if ([car respondsToSelector:name])
{
[anInvocation invokeWithTarget:car];
}else
{
[self doesNotRecognizeSelector:name];
} } //消息转发的时候这种方法会获取一些信息,去创建NSInvocation对象,给- (void)forwardInvocation:(NSInvocation *)anInvocation使用
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [Car instanceMethodSignatureForSelector:aSelector];
} -(void)print
{ // NSLog(@"%@",myName);//成员变量名字,能够由synthesize指定 }
@end
Person类不能响应-(void)setName:(NSString*) name方法时,写了一个Car类进行消息转发,
Car.h
#import <Foundation/Foundation.h> @interface Car : NSObject
{
NSString* myName;
} -(void)setName:(NSString*) name;
@end
Car.m实现
#import "Car.h" @implementation Car -(void)setName:(NSString *)name
{ NSLog(@"setName 在Car里面被调用");
if (![name isEqual:myName])
{
[myName release];
myName=name;
}
}
@end
当我们实现了动态方法决议,又实现了消息转发,那么首先会调用动态方法决议,也不须要进行消息转发了。假设在 resolveInstanceMethod 的实现中没有真正为 selector 提供实现,并返回 NO。那么就会进行消息转发。
下面是实现了动态决议方法成功以及实现了消息转发的执行结果:
2014-07-30 16:27:55.072 MethodNotFind[1774:403] sel is setName:
2014-07-30 16:27:55.073 MethodNotFind[1774:403] 动态决议方法被调用
非常显然动态决议方法被调用了,不会引发crash。
把void dynamicMethodIMP(id self, SEL _cmd)和+ (BOOL)resolveInstanceMethod:(SEL)sel凝视之后。看看执行结果:
2014-07-30 16:28:33.343 MethodNotFind[1786:403] >> forwardInvocation for selector setName:
2014-07-30 16:28:33.343 MethodNotFind[1786:403] setName 在Car里面被调用
非常显然实现了消息转发,也没引发crash。
消息发送的过程:
首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 相应的 IMP。假设没有找到且实现了动态方法决议机制就会进行决议,假设没有实现动态方法决议机制或决议失败且实现了消息转发机制就会进入消息转发流程。
cocoa动态方法决议及消息转发的更多相关文章
- 深入浅出Cocoa之消息(二)-详解动态方法决议(Dynamic Method Resolution) 【转】
序言 如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?根据前文<深入浅出Cocoa之消息>的介绍,我们知道发送消息是通过 objc_send(id, ...
- iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...
本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...
- iOS-Runtime、对象模型、消息转发
Objective-C只是在C语言层面上加了些关键字和语法.真正让Objective-C如此强大的是它的运行时.它很小但却很强大.它的核心是消息分发. Message 执行一个方法,有些语言.编译器会 ...
- runtime之消息转发
前言 在上一篇文章中我们初尝了runtime的黑魔法,可以在程序编译阶段就获取到成员变量的名字,特性以及动态的给对象增加属性等等,在接下来中我们进一步了解OC的消息发送机制.如果之前没接触过runti ...
- iOS 消息转发以及 NSProxy 实战
最后更新: 2018-01-17 一.消息派发机制-NSObject 在 iOS 开发中, 调用对象的方法就是给对象发送一个消息.了解消息的派发机制对于iOS开发来说是一个很实用且强大的工具, 下面我 ...
- iOS消息转发
消息转发是一种功能强大的技术,可以大大增加Objective-C的表现力.什么是消息转发?简而言之,它允许未知的消息被困住并作出反应.换句话说,无论何时发送未知消息,它都会以一个很好的包发送到您的 ...
- Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息
Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息 http://www.cnblogs.com/zhwx/archive/2012/08/28/266055 ...
- iOS开发-消息转发
消息转发是OC运行时比较重要的特性,Objective-C运行时的主要的任务是负责消息分发,我们在开发中"unrecognized selector sent to instance xx& ...
- runtime消息转发机制
Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制.而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库.它是 Objective- ...
随机推荐
- Head First PHP &MySQL学习笔记
近期一段时间在学习PHP,买了<Head First PHP&MySQL>中文版这本书,之前买过<Head First设计模式>,感觉这系列的书籍整体来说非常不错. ...
- python学习——截图工具编写
学习一门语言最好的方法便是实践,想要拿Python写一个截图工具,网上一搜资料果然已经很多,前辈们都已经做的很到位了.现在就一步步来学习一下: 首先学习截图整个桌面的方法,可以使用Python中的PI ...
- 恭喜我开通了CSDN博客
准备在这里写点东西,记录我的学习过程....
- 好多NFS的文章
http://www.cnblogs.com/lidabo/category/587288.html http://www.cnblogs.com/lidabo/p/4380555.html
- heap表和iot表排序规则不同
heap 和iot 对比 OBJECT_NAME OBJECT_TYPE --------------------------------------------------------------- ...
- 虚拟机安装中文Fedora14和C/C++IDE开发环境
虚拟机安装中文Fedora14和C/C++IDE开发环境 2010-12-05 00:15:58 标签:中文Fedora14 IDE 开发环境 C/C++ 原创作品,允许转载,转载时请务必以超链接形式 ...
- 静态书架和js模拟翻书效果
书籍图片随便找了个,有点难看,须要的自己替换个好看点的png格式图片 源代码下载:http://download.csdn.net/detail/sweetsuzyhyf/7604091
- hdu 4455 Substrings (DP 预处理思路)
Substrings Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- Android菜鸟的成长笔记(9)——Intent与Intent Filter(下)
原文:[置顶] Android菜鸟的成长笔记(9)——Intent与Intent Filter(下) 接着上一篇的内容,下面我们再来看看Intent的Data与Type属性. 一.Data属性与Typ ...
- error: /usr/include/stdio.h: Permission denied 的一种情况分析
error: /usr/include/stdio.h: Permission denied 的一种情况分析 代码: #include <stdio.h> int main(){ prin ...