消息转发机制的回顾以及涉及的几个方法
一、OC消息发送原理 + 消息转发机制
1、由于OC的动态特性,只有当程序运行起来之后,才知道要真正执行哪个函数(动态绑定)。在编译过程向类发送了其无法理解的消息并不会报错,因为在运行时,我们可以改变对象调用的方法、向类中添加方法。
2、OC消息发送原理、方法查找过程
(1)调用一个方法(包括respondsToSelector),编译器将OC代码,转换成C函数,给对象发送消息 : void objc_msgSend(id self, SEL cmd,…) ,第一个参数是接收者,第二个参数是方法(名),后面是消息的参数。
(2)objc_msgSend查找方法的过程:
实例对象根据其isa指针,找到其所属的class,然后遍历其methodLists,如果找到则根据IMP函数指针去调用,并且缓存(objc_cache);如果没有找到,那么根据这个类的super_class找到其父类,再看其父类是否能相应这个方法就可以了,直到super_class为nil时,就无法响应这个方法了,此时就触发消息转发机制。
当使用类名调用类方法(+方法)时,只需要根据class的isa指针,找到其meta-class,然后通过meta-class的methodLists找到相应的方法既可(“类”是“元类”的对象)。
3、如果对象接收到无法解读的消息后(未查询到该方法),就会启动“消息转发”机制,我们可在此过程告诉对象应该如何处理未知消息。如果我们不做任何处理,或处理无效,则会调用doesNotRecognizeSelector:,造成异常崩溃:unrecognized selector sent to instance 0xxx
二、消息转发机制的处理过程
消息转发机制依次的三个过程:
1、动态方法解析
第一阶段,先征询接收者所属的类,是否需要动态的添加方法,用来处理当前未找到的方法。对象在无法解读消息时会首先调用所属类的下列类方法,来判断是否能接收消息:
+ (BOOL) resolveInstanceMethod:(SEL)selector,参数为那个未知的选择子,返回值表示这个类能否新增一个实例方法处理此选择子。
如果是类方法 ,则调用 + (BOOL) resolveClassMethod:(SEL)selector,有一点要注意,类方法的添加需要在其“元类”里面。
举例:
//消息转发机制的第一步 :动态方法解析
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSString *selName = NSStringFromSelector(sel);
if ([selName hasPrefix:@"doSomeThing"]) {
//判断特定无法响应的方法
class_addMethod(self, sel, (IMP)otherOneDoSomeThing, "v@:");//动态添加响应方法
return YES;
}
return [super resolveInstanceMethod:sel];
}
//动态将实现转到这个函数(或者就是单纯的添加doSomeThing方法)
void otherOneDoSomeThing(id self ,SEL _cmd){
NSLog(@"class:%@, sel:%s",self,sel_getName(_cmd));
NSLog(@"原对象无法响应该消息,在动态方法解析时添加了一个方法来处理该消息");
}
2、备用的接收者
第二阶段,如果动态方法解析没有发现添加的方法,那么尝试转发给其他对象来处理这个方法。该步骤调用的方法是:
- (id) forwardingTargetForSelector:(SEL)selector
举例:
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSString * selString = NSStringFromSelector(aSelector

最低0.47元/天 解锁文章
948

被折叠的 条评论
为什么被折叠?



