消息发送机制&消息转发机制

2018-06-23  本文已影响80人  Colin_狂奔的蚂蚁

消息发送机制&消息转发机制

消息转发机制图.png

消息转发的三种方式:

// 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
上一篇下一篇

猜你喜欢

热点阅读