美文网首页
iOS消息转发机制

iOS消息转发机制

作者: 猪猪行天下 | 来源:发表于2022-01-11 09:38 被阅读0次

NSObject的一些方法

+ (BOOL)resolveClassMethod:(SEL)sel ;
+ (BOOL)resolveInstanceMethod:(SEL)sel ;

这两个函数在运行时,没有找到SEL的IMP时就会执行,一个是类方法,一个是实例方法。这两个函数是给类利用class_addMethod添加函数的机会,如果实现了添加函数代码则返回YES,未实现返回NO。

- (id)forwardingTargetForSelector:(SEL)aSelector ;

这个方法是系统给了个将这个SEL转给其他对象的机会。 返回参数是一个对象,如果这个对象非nil、非self的话,系统会将运行的消息转发给这个对象执行。否则,继续查找其他流程

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector ;

这个函数和后面的forwardInvocation:是最后一个寻找IMP的机会。这个函数让重载方有机会抛出一个函数的签名,再由后面的forwardInvocation:去执行。

- (void)forwardInvocation:(NSInvocation *)anInvocation ;

在这个函数里可以将NSInvocation多次转发到多个对象中,这也是这种方式灵活的地方。(forwardingTargetForSelector只能以Selector的形式转向一个对象)

- (void)doesNotRecognizeSelector:(SEL)aSelector;

作为找不到函数实现的最后一步,NSObject实现这个函数只有一个功能,就是抛出异常。虽然理论上可以重载这个函数实现保证不抛出异常(不调用super实现),但是苹果文档着重提出“一定不能让这个函数就这么结束掉,必须抛出异常”。

方法转发流程

下面一张图详细的概括了每个函数调用的先后以及执行的前提

005COTsZzy7fFDAwP1B4f.jpg

Objective-C是一门动态语言,一个函数是由一个selector(SEL),和一个implement(IMP)组成的。Selector相当于地址,而Implement则是真实的地点(函数实现)。

和现实生活一样,地址可以随便写(@selector(XXX)),但是不一定都找得到这个地点,如果找不到系统会给程序几次机会来程序正常运行,实在没出路了才会抛出异常。

对应流程图就是:
在一个函数找不到时,Objective-C提供了三种方式去补救:
1、调用resolveInstanceMethod给个机会让类添加这个实现这个函数

2、调用forwardingTargetForSelector让别的对象去执行这个函数

3、调用methodSignatureForSelector(函数符号制造器)和forwardInvocation(函数执行器)灵活的将目标函数以其他形式执行。

4、如果都不中,调用doesNotRecognizeSelector抛出异常。

流程验证

定义一个类Runing

@interface Runing : NSObject

-(void)myClassA;

-(void)myClass;

@end

@implementation Runing

+ (BOOL)resolveInstanceMethod:(SEL)sel{
//运行时,可在此动态添加方法
    NSLog(@" %s",__func__);

        return NO;

}
- (id)forwardingTargetForSelector:(SEL)aSelector{
//在此可实现消息转发给他的对象 
NSLog(@" %s",__func__);

    return nil;

}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{

           NSLog(@" %s",__func__);

     //return nil;       

   NSMethodSignature *methodSignature = [NSMethodSignature  signatureWithObjCTypes:"v@:@"];

   return methodSignature;   

}
- (void)forwardInvocation:(NSInvocation *)anInvocation{

        NSLog(@" %s",__func__); 

//若不调用super,找不到对应的方法实现则抛弃方法,结束流程!

     [super forwardInvocation:anInvocation];

    }

- (void)doesNotRecognizeSelector:(SEL)aSelector{

//若不调用super方法,则不会抛出异常

    NSLog(@" %s",__func__);

}
-(void)myClassA{

        NSLog(@"myClassA");

    }

@end

然后我们调用Runing的方法

Runing *runing = [[Runing alloc] init];

[runing performSelector:@selector(myClass)];

从上面我们可以看到myClass方法我们只是定义了,但是没有去实现。
流程分析:

  1. 因为没有找到myClass的实现,所以会执行resolveInstanceMethod方法,再次可以动态的添加方法的实现。若不添加则继续查找。

  2. 系统使用forwardingTargetForSelector方法,将myClass方法转给其返回值对象去执行。如果返回值是nilself则继续查找。

  3. methodSignatureForSelector方法会抛出一个函数签名,因为myClass方法没有实现,所以使用aSelector参数来抛出函数签名则会返回nil直接到流程5,所以这里用了一个固定值"v@:@",来返回一个NSMethodSignature类型。然后则会重复流程1查找IMP,找不到才会进入下一步

  4. forwardInvocation是最后一个寻找IMP的机会,它可以灵活的将目标函数以其他形式执行而不报错!如果调用super方法,则会继续执行。

  5. doesNotRecognizeSelector最后没有识别myClass方法,则抛弃并不抛出异常。如果实现该方法的super方法则会抛出异常!

相关文章

  • 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/qsamcrtx.html