ios底层开发消息机制(三)动态方法决议

序言

如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?根据前文《深入浅出Cocoa之消息》的介绍,我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 对应的 IMP;如果没有找到且实现了动态方法决议机制就会进行决议,如果没有实现动态方法决议机制或决议失败且实现了消息转发机制就会进入消息转发流程,否则程序 crash。也就是说如果同时提供了动态方法决议和消息转发,那么动态方法决议先于消息转发,只有当动态方法决议依然无法正确决议 selector 的实现,才会尝试进行消息转发。在前文中,我并没有详细讲解动态方法决议,因此本文将详细介绍之。

1 #import <Foundation/Foundation.h>
2
3 @interface PrettyGirl : NSObject
4
5 -(void)loveMe;
6
7 @end
 1 #import "PrettyGirl.h"
 2
 3 @implementation PrettyGirl
 4
 5 -(void)loveMe
 6 {
 7     NSLog(@"Pretty Girl Love Me!");
 8 }
 9
10 @end
 1 #import <Foundation/Foundation.h>
 2 #import "PrettyGirl.h"
 3
 4 int main (int argc, const char * argv[])
 5 {
 6
 7     @autoreleasepool {
 8
 9         PrettyGirl *xiaoQian=[[PrettyGirl alloc]init];
10         [xiaoQian loveMe];
11         [xiaoQian Movie];
12         [xiaoQian release];
13
14     }
15     return 0;
16 }

运行结果

 1 2014-10-27 21:03:25.899 DeeoIntoMethod[4010:303] Pretty Girl Love Me!
 2 2014-10-27 21:03:25.901 DeeoIntoMethod[4010:303] -[PrettyGirl Movie]: unrecognized selector sent to instance 0x100200980
 3 2014-10-27 21:03:25.902 DeeoIntoMethod[4010:303] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException‘, reason: ‘-[PrettyGirl Movie]: unrecognized selector sent to instance 0x100200980‘
 4 *** First throw call stack:
 5 (
 6     0   CoreFoundation                      0x00007fff8a13925c __exceptionPreprocess + 172
 7     1   libobjc.A.dylib                     0x00007fff8c866e75 objc_exception_throw + 43
 8     2   CoreFoundation                      0x00007fff8a13c12d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
 9     3   CoreFoundation                      0x00007fff8a097272 ___forwarding___ + 1010
10     4   CoreFoundation                      0x00007fff8a096df8 _CF_forwarding_prep_0 + 120
11     5   DeeoIntoMethod                      0x0000000100001acd main + 125
12     6   DeeoIntoMethod                      0x0000000100001a44 start + 52
13     7   ???                                 0x0000000000000001 0x0 + 1
14 )
15 libc++abi.dylib: terminating with uncaught exception of type NSException
[PrettyGirl Movie]: unrecognized selector sent to instance 0x100200980这句表示在方法列表中查找不到方法,因此程序crash

好了,这里我们用动态决议来解决这个问题
 1 #import <Foundation/Foundation.h>
 2 #import "PrettyGirl.h"
 3
 4 int main (int argc, const char * argv[])
 5 {
 6
 7     @autoreleasepool {
 8
 9         PrettyGirl *xiaoQian=[[PrettyGirl alloc]init];
10         [xiaoQian loveMe];
11         [xiaoQian Movie];
12         [xiaoQian release];
13     }
14     return 0;
15 }
1 #import <Foundation/Foundation.h>
2
3 @interface PrettyGirl : NSObject
4
5 -(void)loveMe;
6
7 @end
 1 #import "PrettyGirl.h"
 2 #include <objc/runtime.h>
 3
 4 void putonCoat(NSString *str)
 5 {
 6     NSLog(@" >> putonCoat.");
 7 }
 8
 9
10 @implementation PrettyGirl
11
12 -(void)loveMe
13 {
14     NSLog(@"Pretty Girl Love Me!");
15 }
16
17 +(BOOL)resolveClassMethod:(SEL)sel
18 {
19    if(sel==@selector(Movie))
20    {
21        class_addMethod([self class],sel,(IMP)putonCoat,"[email protected]:@");
22    }
23     return [super resolveClassMethod:sel];
24 }
25
26 +(BOOL)resolveInstanceMethod:(SEL)sel
27 {
28     if(sel==@selector(Movie))
29     {
30         class_addMethod([self class],sel,(IMP)putonCoat,"[email protected]:@");
31     }
32     return [super resolveClassMethod:sel];
33 }
34
35 @end
class_addMethod方法第一个参数是要执行的类[self class],第二个参数是方法名sel,第三个参数是要代替的方法指针,最后一个方法是参数参数解释:i:返回int类型,v表示无返回值@:参数id(self):SEL(_cmd)@:id(str)
时间: 2024-10-13 21:33:00

ios底层开发消息机制(三)动态方法决议的相关文章

ios底层开发消息机制(四)消息转发

消息转发 若想令类能理解某条消息,我们必须以程序码实现出对应的方法才行.但是,在编译期向类发送了其无法解读的消息并不会报错,因为在运行期可以继续向类中添加方法,所以编译器在编译时还无法确知类中到底会不会有某个方法实现.当对象接收到无法解读的消息后,就会启动“消息转发”(message forwarding)机制,程序员可经由此过程告诉对象应该如何处理未知消息. 你可能早就遇到过经由消息转发流程所处理的消息了,只是未加留意.如果在控制台中看到下面这种提示信息,那就说明你曾向某个对象发送过一条其无法

ios底层开发消息机制(二)消息调用过程

上一章节对基础概念有了些了解,我们对ObjC 中的消息应该有个大致思路了:示例 Bird * aBird = [[Bird alloc] init]; [aBird fly]; 中对 fly 的调用,编译器通过插入一些代码,将之转换为对方法具体实现IMP的调用,这个 IMP是通过在 Bird 的类结构中的方法链表中查找名称为fly 的 选标SEL 对应的具体方法实现找到的. 上面的思路还有一些没有提及的话题,比如说编译器插入了什么代码,如果在方法链表中没有找到对应的 IMP又会如何,这些话题在下

ios底层开发消息机制(一)基本概念

在入门级别的ObjC 教程中,我们常对从C++或Java 或其他面向对象语言转过来的程序员说,ObjC 中的方法调用(ObjC中的术语为消息)跟其他语言中的方法调用差不多,只是形式有些不同而已. 譬如C++ 中的: Bird * aBird = new Bird(); aBird->fly(); 在ObjC 中则如下: Bird * aBird = [[Bird alloc] init]; [aBird fly]; 初看起来,好像只是书写形式不同而已,实则差异大矣.C++中的方法调用可能是动态的

深入浅出Cocoa之消息(二)-详解动态方法决议(Dynamic Method Resolution) 【转】

序言 如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?根据前文<深入浅出Cocoa之消息>的介绍,我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 对应的 IMP:如果没有找到且实现了动态方法决议机制就会进行决议,如果没有实现动态方法决议机制或决议失败且实现了消息转发机制就会进入消息转发流

动态方法决议 和 消息转发

如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 对应的 IMP:这个是需要对类对象的结构熟悉,不清楚的可以参考我的下一篇文章<object-c 类结构解析>,如果没有找到且实现了动态方法决议机制就会进行决议,如果没有实现动态方法决议机制或决

2、struct2开发action 的三种方法以及通配符、路径匹配原则、常量

struct2 开发action 的三种方法 1.继承ActionSupport public class UserAction extends ActionSupport { // Action中业务处理方法 public String login() { System.out.println("UserAction.login()"); // return "success"; return SUCCESS; } } 2.实现Action public clas

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;

struts2开发action 的三种方法以及通配符、路径匹配原则、常量

struts2开发action 的三种方法 1.继承ActionSupport public class UserAction extends ActionSupport { // Action中业务处理方法 public String login() { System.out.println("UserAction.login()"); // return "success"; return SUCCESS; } } 2.实现Action public class

iOS NSNotificationCenter(消息机制)

转自:http://blog.csdn.net/liliangchw/article/details/8276803 对象之间进行通信最基本的方式就是消息传递,在Cocoa中提供Notification Center机制来完成这一任务.其主要作用就是负责在任意两个对象之间进行通信.使用方法很简单,如下几个步骤即可: 假设A与B之间进行通信,B来触发事件,A接受该事件,并作出响应.1) A编写自定义的消息响应函数update2) A向消息中心注册,[NSNotificationCenter def