Objective-c 消息转发机制

参考资料:

Obejective-c 消息是什么

小萝莉说crash


消息转发流程:

在Objective-c一文中说到,对象在函数列表中找不到SEL或者找不到SEL对应的IMP实现的时候就会进入消息转发流程。流程如下:




图中的IML的意思应该就是“ Objective-c 消息是什么”文章中的通过SEL 查找IMP实现的过程。


+(BOOL)resolveInstanceMethod:(SEL)sel  方法拦截消息

这个消息拦截的作用在于给个机会给本对象动态添加需要的selector。

先来看个例子:

Fish类:

#import <Foundation/Foundation.h>
@interface Fish : NSObject
-(void)fishDescribeYouSelf;
@end

#import "Fish.h"
#import <objc/message.h>
@implementation Fish
-(void)fishDescribeYouSelf{
    NSLog(@"I am fish");
}

-(void)_fishMethodNotExit{
    NSLog(@"_fishMethodNotExit");
}

//查找动态指定的IMP
+(BOOL)resolveInstanceMethod:(SEL)sel{
    
    if (sel == NSSelectorFromString(@"fishMethodNotExit")) {
        IMP _fishMethodNotExit = [Fish instanceMethodForSelector:@selector(_fishMethodNotExit)];
        class_addMethod([self class], sel, _fishMethodNotExit, "v@:");  //v@:  第一个字符代表返回的值是void,@是self的类型id,:是_cmd的类型SEL。(Objective-c中的方法默认被隐藏了两个参数:self指向对象本身,_cmd指向方法本身)。如果是@@:则代表返回值是字符串,f@:代表返回值是浮点型
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}
@end

调用:

Fish *fish = [[Fish alloc] init];
[fish fishMethodNotExit];
程序不会崩溃并且输出:_fishMethodNotExit。找不到fishMethodNotExit的时候,系统调用了 resolveInstanceMethod,并且给找不到的SEL动态添加了IMP,使得调用_fishMethodNotExit这个函数。


-(id)forwardingTargetForSelector:(SEL)aSelector 拦截消息并且处理

没有在resolveInstanceMethod实现相关的动态添加,不管返回值是否为YES,消息则会来到快速转发forwardingTargetForSelector。

这个消息拦截的作用在于,给个机会把消息转发给另外一个对象

看例子,新增一个Flower类:

#import <Foundation/Foundation.h>

@interface Flower : NSObject
-(void)fishMethodNotExit;
@end

@implementation Flower
-(void)fishMethodNotExit{
    NSLog(@"fishMethodNotExit in Flower");
}
@end


去掉Fish类的resolveInstanceMethod,添加forwardingTargetForSelector的实现。

-(id)forwardingTargetForSelector:(SEL)aSelector{
    Flower *flower = [[Flower alloc] init];
    if ([flower respondsToSelector:aSelector]) {
        return flower;
    }
    
    return self;
}

调用:

    Fish *fish = [[Fish alloc] init];
    [fish fishMethodNotExit];

输出:

fishMethodNotExit in Flower



methodSignatureForSelector:   forwardInvocation:

如果resolveInstanceMethod 和 forwardingTargetForSelector没有对消息进行处理,则来到标准转发



















  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值