runtime(消息转发)

概况

当一个方法沿着类的继承链找不到实现时候,runtime会启动消息转发。消息转发一共有三步。

消息转发三步
  1. resolveInstanceMethod
#import "Cat.h"
#import <objc/runtime.h>

@implementation Cat
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if ([NSStringFromSelector(sel) isEqualToString:@"say"]) {
        class_addMethod(self, sel,(IMP)test , "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void test(id self,SEL cmd){
    NSLog(@"猫叫...");
}
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Cat *aCat = [[Cat alloc] init];
    [aCat say];
}
@end

在调用对象的所属类的实现文件新增resolveInstanceMethod方法。判断选择子是不是我们要进行转发的,如果不是返回super方法。如果是就新增方法的实现,并返回YES消息转发结束。

  1. forwardingTargetForSelector
#import "Dog.h"
#import "Cat.h"
#import <objc/runtime.h>

@implementation Dog

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if ([NSStringFromSelector(sel) isEqualToString:@"say"]) {
        return NO;
    }
    return [super resolveInstanceMethod:sel];
}

- (id)forwardingTargetForSelector:(SEL)aSelector{
    return [Cat new];
}
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Dog *aDog = [[Dog alloc] init];
    [aDog say];
}
@end

在调用所属类的实现文件里新增resolveInstanceMethod方法如果是当前选择子返回NO好进行消息转发第二步。接下来新增方法forwardingTargetForSelector返回cat对象。之后runtime系统会去cat类里去调用say的实现。

  1. forwardInvocation
#import "Dog.h"
#import "Cat.h"
#import <objc/runtime.h>

@implementation Dog

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if ([NSStringFromSelector(sel) isEqualToString:@"say"]) {
        return NO;
    }
    return [super resolveInstanceMethod:sel];
}

- (id)forwardingTargetForSelector:(SEL)aSelector{
    return nil;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    SEL aSel = anInvocation.selector;
    Cat *aCate = [Cat new];
    if ([aCate respondsToSelector:aSel]) {
        [anInvocation invokeWithTarget:aCate];
    }
}
@end

在调用类的实现文件里,新增resolveInstanceMethod方法返回NO,进入消息转发第二步。新增forwardingTargetForSelector方法返回nil,进入消息转发第三步。新增方法methodSignatureForSelector,forwardInvocation实现完整的消息转发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值