iOS 消息转发机制

作者: Dylan_J | 来源:发表于2019-11-07 09:53 被阅读0次

Objective-C中的方法转成消息发送后,会在相关的类对象中搜索方法列表,如果找不到则会沿着继承树向上一直搜索直到NSObject,如果找不到就执行doesNotRecongnizeSelector方法报unrecognizes selector。
但是在报错之前,有三次处理问题的机会。
1.动态方法分析
2.备用接收者
3.完整消息转发


消息转发.png

动态方法分析

Objective-C运行时会调用+resolveInstanceMethod:或者+resloveClassMethod:,提供一个函数实现。如果返回YES,那运行时系统会重新启动一次消息发送过程。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self performSelector:@selector(func:)];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if(sel == @selectot(func:)) {
        class_addMethod([self class], sel, (IMP)funcMethod, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void funcMethod(id obj, SEL _cmd) {
    NSLog(@"Action");
}

可以看到虽然没有实现func:方法,但是我们通过class_addMethod动态添加了funcMethod方法,并执行funcMethod这个方法的IMP。

如果resolve方法返回NO,运行时就会移到下一步:forwardingTargetForSelector。

备用接收者

如果目标对象实现了-forwardingTargetForSelector:,Runtime这时会调用这个方法,把消息转发给其他对象。

#import "objc/runtime.h"

@interface Object: NSObject

@end

@implementation Object

- (void)func {
    NSLog(@"func action!");
}

@end
#import "objc/runtime.h"

@interface ViewController: NSObject

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self performSelector:@selector(func)];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    return NO;
}

- (id)forwardingTargetForSelector:(SEL)sel {
    if (sel == @selector(func)) {
        return [Object new];
    }
    return [super forwardingTargetForSelector:sel];
}

@end

通过forwardingTargetForSelector把当前ViewController的方法转发给Object执行。

完整消息转发

如果前两步都不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。
首先发送-methodSignatureForSelector:消息获取函数的参数及返回值类型。如果-methodSignatureForSelector:返回nil,Runtime会发出-doesNotRecognizeSelector:消息,程序这时也就挂了。如果返回一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:消息给目标对象。

#import "objc/runtime.h"

@interface Object: NSObject

@end

@implementation Object

- (void)func {
    NSLog(@"func action!");
}

@end
#import "objc/runtime.h"

@interface ViewController: NSObject

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self performSelector:@selector(func)];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    return NO;
}

- (id)forwardingTargetForSelector:(SEL)sel {
    return nil;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    if ([NSStringFromSelector(sel) isEqualToString:@"func"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"]; // 签名,进入forwardInvocation
    }
    return [super methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    SEL sel = invocation.selector;
    Object *obj = [Object new];
    if ([obj respondsToSelector:sel]) {
        [invocation invokeWithTarget:obj];
    }else {
        [self doesNotRecognizeSelector:sel];
    }
}

@end

通过签名,Runtime生成了一个对象,发送forwardInvocation,方法里面让Object对象执行func方法。
以上就是Runtime的三次转发流程。

相关文章

  • runtime系列文章总结

    《iOS Runtime详解(消息机制,类元对象,缓存机制,消息转发)》《消息转发机制与Aspects源码解析》《...

  • iOS理解Objective-C中消息转发机制附Demo

    iOS理解Objective-C中消息转发机制附Demo iOS理解Objective-C中消息转发机制附Demo

  • iOS面试-基础

    [toc] Runloop AutoReleasePool 多线程 响应者链 消息响应机制 消息转发机制 iOS内...

  • iOS 消息转发机制

    今天大概学习了下iOS的消息转发机制,还是挺有收获,在此做下笔记,以便后面温习。 1.iOS的消息转发机制原理如下...

  • iOS面试题总结(二)

    iOS面试题(二) 消息发送和转发机制,SEL和IMP 消息发送转载自黄龙辉消息发送和消息转发机制 在Object...

  • Runtime

    相关简单介绍 消息机制消息传递机制消息转发机制-动态添加方法消息转发机制-快速转发消息转发机制-慢速转发消息转发机...

  • iOS - 消息转发机制

    我们知道,OC是动态语言,所有的方法都会以消息的形式传递给对象,对象会根据方法的类型来进行实例方法或者类方法的选择...

  • 【iOS】消息转发机制

    1、动态方法解析 对象在收到无法处理的消息时,会调用下面的方法,前者是调用类方法时会调用,后者是调用对象方法时会调...

  • iOS消息转发机制

    OC消息转发 oc中的调用对象或者类不存在的方法,会执行一遍消息转发流程.消息转发主要包括4步 首先调用+ (BO...

  • iOS 消息转发机制

    iOS开发过程中我们经常会碰到这样的报错:unrecognized selector sent to instan...

网友评论

    本文标题:iOS 消息转发机制

    本文链接:https://www.haomeiwen.com/subject/plymbctx.html