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