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

iOS 消息转发机制小结

作者: 金天动地 | 来源:发表于2019-06-20 10:49 被阅读0次

联想

消息转发有点类似一起听说过的一个故事<<上帝的拯救>>,一次发洪水,传教士笃信上帝会当面就他,多次错过人其他人对他的帮助.其实那些人就是上帝派来拯救他.可惜传教士不懂变通,只能去见上帝了.

话题开头:

某个对象/类 调用方法,但是确没有实现该方法,最后给四次挽救的机会,若错过了,就只能"去见上帝了"
总体流程图如下:

image.png

测试代码如下

  1. 创建一个Person类,仅在头文件进行方法的声明:
#pragma mark - 测试消息转发
- (void)testForwardMethod:(NSString*)methed;

然后在ViewDidLoad进行测试

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    Person *p = [[Person alloc] init];
    
    // TODO: 测试消息转发1
    [p testForwardMethod:@"abc"];
}

若此时运行,💥奔溃

image.png
来进行救赎第一次救赎:
注意:
1.1. 明确方法:确定是类方法还是对象方法
1.2. 调用 +resolveClassMethod: 或者resolveInstanceMethed
1.3. 由于本测试是对象方法, 实现方法如下.注意不要只返回YES,没有进行方法处理,那么结果还是奔溃.
void myMethodIMP(id self, SEL _cmd, id paragram)
{
    NSLog(@"第一次救赎成功,参数:%@",paragram);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
    // 参数1: 要添加的类 参数2: 选择子/选择器(方法名) 参数3:方法的实现(方法函数) 参数4: 方法类型
    // v@:@ 说明: v->返回值类型; @->代表方法第一个参数:self, :->代表选择器/选择子 @->代表第一个参数
    // 具体查看
    class_addMethod(self, sel, (IMP)myMethodIMP, "v@:@");
    return YES;
}

第一次救赎结果如下:

image.png
来进行救赎第二次救赎:
注意:(让其他类来执行)
2.1. 调用 +resolveClassMethod: 或者+resolveInstanceMethed 注释掉或者返回NO
2.2 在-forwardingTargetForSelector:进行判是否转发给有现实这个方法的对象或者类.
- (id)forwardingTargetForSelector:(SEL)aSelector {
    Helper *helper = [[Helper alloc] init];
    if([helper respondsToSelector:aSelector]) {
        return helper;
    } else {
        return nil;
    }
}

2.3. 转发的类要实现-testForwardMethod:方法,若没有实现相关方法,还是奔溃

#pragma mark - 测试消息转发2(其它类实现了方法)
- (void)testForwardMethod:(NSString*)methed {
    NSLog(@"上帝的第二次救赎成功:%s -- %@ --- %@",__func__, methed, self);
}

第二次救赎结果如下:

image.png

来进行救赎第三次救赎:
注意:
3.1. 转发的类要实现-testForwardMethod:方法,注释掉,第二次救赎-forwardingTargetForSelector:返回nil 类型编码详见
3.2 实现 -methodSignatureForSelector: 通过正确的类型方法方法签名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}

3.3 只要实现forwardInvocation: 就不会奔溃了


image.png

不过还要进行正确的处理,例如转接给otherHelper处理,或者自己添加方法.
3.4 在forwardInvocation: 添加代码如下

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    // 将其转交给helper
    OtherHelper *otherHelper = [[OtherHelper alloc] init];
    if([otherHelper respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:otherHelper];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

3.5 注意:NSInvocation 方法的调用,含义target,selector
若要获取参数,和设置参数的时候注意隐含的两个参数self, _cmd 索引为2开始,注意获取self, _cmd 通过索引,获取self值的时候可能奔溃??
获取参数之前地址

image.png
获取参数之后的地址,还会返回去调用.原因未找到?
image.png
- (void)getArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
- (void)setArgument:(void *)argumentLocation atIndex:(NSInteger)idx;

第三次救赎结果如下:
转发其他类来处理

image.png
自己添加方法来处理
image.png

来进行救赎第四次救赎:
事不过三,何况操过三次了.处理基本都已经结束了.
实现:-doesNotRecognizeSelector: 在此方法中抛出错误! 然后奔溃💥

image.png

相关文章

  • iOS 消息转发机制小结

    联想 消息转发有点类似一起听说过的一个故事<<上帝的拯救>>,一次发洪水,传教士笃信上帝会当面就他,多次错过人其他...

  • 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 消息转发机制小结

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