动态方法决议 和 消息转发
假设我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 相应的 IMP;这个是须要对类对象的结构熟悉,不清楚的能够參考我的下一篇文章《object-c 类结构解析》,假设没有找到且实现了动态方法决议机制就会进行决议,假设没有实现动态方法决议机制或决议失败且实现了消息转发机制就会进入消息转发流程,否则程序 crash。也就是说假设同一时候提供了动态方法决议和消息转发,那么动态方法决议先于消息转发,仅仅有当动态方法决议依旧无法正确决议 selector 的实现,才会尝试进行消息转发。
1. 什么是动态方法决议
Objective C 提供了一种名为动态方法决议的手段,使得我们能够在执行时动态地为一个 selector 提供实现。我们仅仅要实现 +resolveInstanceMethod: 或 +resolveClassMethod: 方法,并在当中为指定的 selector 提供实现就可以(通过调用执行时函数 class_addMethod 来加入�)。这两个方法都是 NSObject 中的类方法,其原型为:
+ (BOOL)resolveClassMethod:(SEL)name;
+ (BOOL)resolveInstanceMethod:(SEL)name;
2.消息转发
实现下面这两个方法
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL name = [anInvocation selector];
NSLog(@" >> forwardInvocation for selector %@", NSStringFromSelector(name));
Proxy * proxy = [[[Proxy alloc] init] autorelease];
if ([proxy respondsToSelector:name]) {
[anInvocation invokeWithTarget:proxy];
}
else {
[super forwardInvocation:anInvocation];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [Proxy instanceMethodSignatureForSelector:aSelector];
}
总结
从上面的演示样例演示能够看出,动态方法决议是先于消息转发的。
假设向一个 Objective C 对象对象发送它无法处理的消息(selector),那么编译器会依照例如以下次序进行处理:
1,首先看是否为该 selector 提供了动态方法决议机制,假设提供了则转到 2;假设没有提供则转到 3;
2,假设动态方法决议真正为该 selector 提供了实现,那么就调用该实现,完毕消息发送流程,消息转发就不会进行了;假设没有提供,则转到 3;
3,其次看是否为该 selector 提供了消息转发机制,假设提供了消息了则进行消息转发,此时,不管消息转发是如何实现的,程序均不会 crash。(由于消息调用的控制权全然交给消息转发机制处理,即使消息转发并没有做不论什么事情,执行也不会有错误,编译器更不会有错误提示。);假设没提供消息转发机制,则转到 4;
4,执行报错:无法识别的 selector,程序 crash;
參考:
http://www.cnblogs.com/kesalin/archive/2012/11/14/dynamic_method_resolve.html
http://www.cnblogs.com/biosli/p/NSObject_inherit_2.html
相关文章
- 【说站】python socket发送消息的方法
- sweetviz 生成的 HTML 报告里图表中的中文显示乱码 解决方法
- Allegro给无网络的地孔添加GND网络的方法
- redis中队列消息实现应用解耦的方法
- js实现的map方法详解编程语言
- JSP Exception.getMessage()方法:获取异常消息文本
- Linux调用C静态库的简易方法(linux调用c静态库)
- 恢复MySQL被误删记录的方法(mysql误删)
- Redis 实现消息持久化机制的实践方法(redis消息持久化)
- Linux 系统读写权限设置:最佳实践方法(linux读写权限设置)
- MySQL中now函数的使用方法(mysql中now的用法)
- MySQL无法正常关闭解决方法(mysql不能正常关闭)
- 实现Redis队列数据持久化的方法(redis队列怎么持久化)
- jsURL参数的拼接方法比较
- c++中的消息框messagebox()详细介绍及使用方法
- sqlserver2008中的apply运算符使用方法
- Javascriptalert消息换行的方法
- JSP加载JS文件不起作用的有效解决方法
- ASP.NET中弹出消息框的几种常见方法
- MFC自定义消息的实现方法