Runtime消息转发流程

Step 1:动态方法解析

#import "objc/runtime.h"
- (void)viewDidLoad
{
    [self performSelector:@selector(sayHello)];
}

// 动态方法解析
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(sayHello)) {
        // 动态添加函数到 viewController
        class_addMethod([self class], sel, (IMP)dance, "v@:");
        return YES;  // 即使这边return no,对 forwardingTarget也没有影响
    }
    return [super resolveInstanceMethod:sel];
}

void dance(id obj, SEL _cmd)
{
    NSLog(@"dance");
}

Step 2:重定向

#import "objc/runtime.h"
#import "Dog.h"
- (void)viewDidLoad
{
    [self performSelector:@selector(sayHello)];
}

// 注释 resolve 方法,也会走 forwarding
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// yes or no 都没影响,继续往下走
  return YES;
}

//消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if (aSelector == @selector(sayHello)) {
        return  [Dog new];
    }
    return  [super forwardingTargetForSelector:aSelector];
}

Step 3:完整消息转发

#import "objc/runtime.h"
#import "Dog.h"
- (void)viewDidLoad
{
    [self performSelector:@selector(sayHello)];
}

// 注释 resolve 方法,也会走 forwarding
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// yes or no 都没影响,继续往下走
  return YES; // 进入下一步
}

//可以注释掉
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return  nil;  // 进入下一步
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSLog(@"methodSignatureForSelector");
    if ([NSStringFromSelector(aSelector) isEqualToString: @"sayHello"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"]; // //签名,进入forwardInvocation
    }
    return  [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL sel = anInvocation.selector;
    Person *p = [Person new];
    if ([p respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:p];
    } else {
        [self doesNotRecognizeSelector:sel];
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容