sunhongyue4500
8/14/2017 - 1:54 AM

iOS Message Forward

iOS Message Forward

//
//  Person.m
//  TestMsgForward
//
//  Created by Sunhy on 2017/8/14.
//  Copyright © 2017年 Sunhy. All rights reserved.

// http://www.cocoachina.com/ios/20150604/12013.html

//

#import "Person.h"
#import "Animal.h"
#import "objc/runtime.h"

@implementation Person
//
//- (void)run {
//    
//}

#pragma mark - **************** 动态实现
//+ (BOOL)resolveClassMethod:(SEL)aSEL {
//    if (aSEL == @selector(run))
//    {
//        class_addMethod(object_getClass([self class]), aSEL, (IMP) dynamicMethodIMP, "v@:");
//        return YES;
//    }
//    return [super resolveInstanceMethod:aSEL];
//}
//
//+ (BOOL) resolveInstanceMethod:(SEL)aSEL
//{
//    if (aSEL == @selector(run))
//    {
//        class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
//        return YES;
//    }
//    return [super resolveInstanceMethod:aSEL];
//}

void dynamicMethodIMP(id self, SEL _cmd)
{
    NSLog(@"动态实现实例方法 run");
}

#pragma mark - **************** 动态提供响应者

//- (id)forwardingTargetForSelector:(SEL)aSelector {
//    if (aSelector == @selector(run)) {
//        return [[Animal alloc] init];
//    }
//    return nil;
//}

#pragma mark - **************** 完整消息转发

- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    if (sel == @selector(run)) {
        // v:表示void @表示调用者self :表示_cmd
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return nil;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    // 关于生成签名的类型"v@:"解释一下。每一个方法会默认隐藏两个参数,self、_cmd,self代表方法调用者,_cmd代表这个方法的SEL,签名类型就是用来描述这个方法的返回值、参数的,v代表返回值为void,@表示self,:表示_cmd。
    SEL aSelector = [invocation selector];
    Animal *ani = [[Animal alloc] init];
    if ([ani respondsToSelector:aSelector])
        [invocation invokeWithTarget:ani];
    else
        [super forwardInvocation:invocation];
}

@end