iOS的消息转发机制

2017-05-26  本文已影响150人  StonesMonkey

这里讲的是消息转发机制,如果对象收到无法解读的消息之后会发生什么情况?
我们都知道Objective-c是谁一种动态语言,我们说App运行它要经历两个过程,分别说编译阶段和运行阶段。编译阶段编译器只会判断程序中有没有这个方法,而不会去十分准确的去判断这个方法是否属于调用的对象。如图1

图1:unrecognized selector sent to instance

在编译阶段,编译器对无法解读的方法无法确定对错,毕竟我们都知道我们可以动态的给对象增加方法,当对象接受到无法解读的方法后,就会启动“消息转发(messafe forwarding)”机制,程序经由此过程告诉对象应该如何处理未知消息<这段话来自effective Object - C 2.0>

消息转发流程

图1:消息转发流程图

图片来源于:
http://www.cnblogs.com/ansyxpf/p/5690215.html

要点:

+ (BOOL)resolveInstanceMethod:(SEL)sel

在SMPerson.m方法里面实现这个方法并打印

<pre>
//#import "SMPerson.h"
@implementation SMPerson
// 不让它生成setter和getter方法
@dynamic name;
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"%s",func);
return [super resolveInstanceMethod:sel];
}
@end

// 是为了好看,复制的时候可以去掉
</pre>

图2: 它会调用__fun__

当启动消息转发机制,首先会到<code>+ (BOOL)resolveInstanceMethod:(SEL)sel</code>它是动态给选择器提供一个实现,如果它返回YES,那么会有对这个方法处理的对象,如果返回NO,将跳到下一个消息,去寻找这个方法的处理者。
<code>所以为了让我们的方法得到处理我们可以通过运行时动态给他添加方法</code>

在这个方法动态添加方法

我们都知道,出现的问题是,我们调用的这个setName方法,不存在,那么问题就好解决了,我们添加一个这个方法就好了

<pre>

setter 方法 和getter方法添加的c语言实现

<pre>
void AutoDictionarySetter(id self, SEL _cmd, id vaule) {

NSString *selStr = NSStringFromSelector(_cmd);
// 消除set方法的点和set
NSMutableString *key = [selStr mutableCopy];
[key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];
[key deleteCharactersInRange:NSMakeRange(0, 3)];
// 让它变成小些
NSString *lowSrr = [[key substringFromIndex:0] lowercaseString];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowSrr];

if (vaule) {
    
    [dictStore setValue:vaule forKey:key];
}else {
    
    [dictStore removeObjectForKey:key];
}

}
id AutoDictionarygetter(id self, SEL _cmd) {

NSString *key = NSStringFromSelector(_cmd);
return [dictStore objectForKey:key];

}
</pre>

当我们给当前类动态的补充了这个方法,然后返回YES ,根据图1消息转发所示 返回YES,消息已经被处理,当返回NO的时候呢?

备缓接受者

上面提到,当<code> resolveInstanceMethod </code>接收不到数据的时候,

上一篇下一篇

猜你喜欢

热点阅读