消息发送机制&消息转发机制
- 消息发送机制:使用了运行时的方式, 通过SEL快速查找IMP的过程.
- 消息转发机制:IMP找不到,通过方法进行转发.
消息转发的三种方式:
// 1、动态方法解析
+ (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
// 2、快速消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
// 3、标准的消息转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");
- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
测试代码:
#import "ViewController.h"
#import "Person.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *per = [Person new];
[per run];
}
@end
其它文件:
===================Person文件===================
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void)run;
@end
#import "Person.h"
#import <objc/message.h>
#import "Animation.h"
@implementation Person
// 1.动态方法解析
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"sel = %@", NSStringFromSelector(sel));
// 1.判断没实现方法, 就动态添加方法
if (sel == @selector(run)) {
// 2.动态添加方法
class_addMethod(self, sel, (IMP)newRun, "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
void newRun(id self,SEL sel, NSString *str) {
NSLog(@"---run起来了没有 %@--",str);
}
// 二.消息转发重定向
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSLog(@"%@",NSStringFromSelector(aSelector));
if (aSelector == @selector(run)) {
return [[Animation alloc] init];
}
return [super forwardingTargetForSelector:aSelector];
}
// 三.生成方法签名.
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
// 1. 转化字符串
NSString *sel = NSStringFromSelector(aSelector);
// 2.进行判断 手动生成签名
if ([sel isEqualToString:@"run"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
} else {
return [super methodSignatureForSelector:aSelector];
}
}
// 四.拿到方法签名配发消息
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"-----%@",anInvocation);
// 1.拿到这个消息
SEL selector = [anInvocation selector];
// 2.转发消息.
Animation *anm = [[Animation alloc] init];
if ([anm respondsToSelector:selector]) {
// 调用这个对象,进行转发
[anInvocation invokeWithTarget:anm];
} else {
[super forwardInvocation:anInvocation];
}
}
// 五.抛出异常
- (void)doesNotRecognizeSelector:(SEL)aSelector {
NSString *selStr = NSStringFromSelector(aSelector);
NSLog(@"这个-----%@---方法不存在", selStr);
}
@end
===================Animation文件===================
#import <Foundation/Foundation.h>
@interface Animation : NSObject
- (void)run;
- (void)eat;
@end
#import "Animation.h"
@implementation Animation
- (void)run {
NSLog(@"%@---Animation--run", self);
}
- (void)eat {
NSLog(@"%@---Animation--eat", self);
}
@end