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];
    }
}

你可能感兴趣的:(Runtime消息转发流程)