美文网首页开发者iOS开发Objective-C
Runtime系列(消息转发)

Runtime系列(消息转发)

作者: 01_Jack | 来源:发表于2015-08-28 07:29 被阅读2395次

前言

一个方法的声明必定会有与之对应的实现,如果调用了只有声明没有实现的方法会导致程序crash,而实现并非只有中规中矩的在.m里写上相同的方法名再在内部写实现代码。

正文

先来回顾一下引文中的部分内容:
当调用[receiver message]时,会触发id objc_msgSend(id self, SEL op, ...)这个函数。
receiver通过isa指针找到当前对象的class,并在class中寻找op,如果找到,调用op,如果没找到,到super_class中继续寻找,如此循环直到NSObject(引自引文)。
如果NSObject中仍然没找到,程序并不会立即crash,而是按照优先级执行下列三个方法(下列方法优先级依次递减,高优先级方法消息转发成功不会再执行低优先级方法):

1.+ resolveInstanceMethod:(SEL)sel // 对应实例方法
  + resolveClassMethod:(SEL)sel // 对应类方法
2.- (id)forwardingTargetForSelector:(SEL)aSelector
3.- (void)forwardInvocation:(NSInvocation *)anInvocation
举例

比如在ViewController.h中声明,并且不在ViewController.m中直接实现,如何确保程序正常运行

@interface ViewController : UIViewController
- (void)sayHello:(NSString *)name;

@end
resolveInstanceMethod:

以实例方法为例:

resolveInstanceMethod 1.png

说一下这个函数

class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>)

cls表示要添加方法的类,name表示要添加方法的SELimp表示要添加方法的IMPtypes表要添加方法的返回值和参数类型。
上篇文章已经说过SELIMP的异同,也许你会想这里的nameimp参数是否重复,毕竟receiver已经明确,无论通过SEL还是IMP都是可以找到对应函数\方法的。正常情况是这样,但是这里只有声明没有常规的实现,如果只有SEL会导致找不到入口,如果只有IMP会导致函数\方法名不确定。
示例中type的值为v@:@,如果不用imp_implementationWithBlock来写可能更好理解

resolveInstanceMethod 2.png

v@:@中:v对应着返回值void第一个@对应着第一个参数类型id:对应着第二个参数类型SEL第二个@对应着三个参数类型NSString关于Type Encodings可参考官方文档

forwardingTargetForSelector:
forwardingTargetForSelector.png Message.h.png Messsage.m.png

将ViewController中调用的实例方法转移到Message中,这里很好理解无须赘述。

forwardInvocation:
forwardInvocation.png

同样,这里是将ViewController中调用的实例方法转移到Message中,只是多了一层NSInvocation包装,有利于我们做更多的事情。

相关文章

  • Runtime系列(消息转发)

    前言 一个方法的声明必定会有与之对应的实现,如果调用了只有声明没有实现的方法会导致程序crash,而实现并非只有中...

  • Aspects原理和使用

    前言 在读这篇文章之前,需要对Runtime消息发送、消息转发有一定的了解。Runtime系列Objective-...

  • Runtime系列之消息转发

    Runtime系列之消息转发 1 消息传递 OC属于动态类型语言,方法的调用是通过发送消息来完成的。objc/ru...

  • Effective Objective-C读后笔记(2)

    11、runtime消息转发机制 runtime的消息转发流程图消息转发 消息转发的示例实现 这里也给大家推荐一篇...

  • iOS - Runtime - 概念和方法交换

    runtime的概述runtime的相关概念runtime消息机制消息传递动态方法解析消息转发runtime的作用...

  • runtime底层实现原理

    一、Runtime介绍二、Runtime源码初探三、Runtime消息传递四、Runtime消息转发五、Runti...

  • Runtime系列4--消息转发

    消息转发原理 简单来说,就是在Objective-C中,使用对象进行方法调用是一个消息发送的过程(Objectiv...

  • runtime 消息转发

    实例方法的消息传递:消息的转发建立在objc_msgSend(id, SEL, ...)来实现的。首先会在类对象的...

  • Runtime 消息转发

    目录 消息转发背景知识 消息转发使用方式 消息转发常见问题 消息转发背景知识 1.消息转发的定义Objective...

  • Runtime消息转发

    我们还是先从实际代码入手吧,首先,我们先新建一个类,就Person类吧,大家刚学OC的时候用的最多的就是Perso...

网友评论

  • iOS程序犭袁:学习下
    01_Jack:@iOS程序犭袁 大牛来访,荣幸之至
  • 南栀倾寒:resolveClassMethod 这个我很早之前都没办法解决 一直crash 实例方法没问题, 是因为方法签名的问题吗?
    南栀倾寒:@iOS_SZT 已经解决了 不是方法签名的事 类方法 要加在 metaClass上面, 因为 类方法其实metaclass 的单例类对象的方法调用
    Carrism:@南栀倾寒 通过resolveClassMethod为类添加类方法我也一直crash,请问你们解决了吗
    01_Jack:@南栀倾寒 有可能,这个要看源码啊
  • ziyouzhe4:您好,文字确实很棒,有些地方不是很懂,希望得到解答,谢谢! forwardingTargetForSelector 和 forwardInvocation 在什么情景下会用呢? 这样 有啥好处?因为不太懂,所以可能问的也不是很准确,学习中,
    ziyouzhe4:@01_Jack 谢谢啦!期待
    01_Jack:@ma_jack 这个月会抽时间写新文章,有相关内容希望可以帮到你
  • 丁小丁iOS:这么高大上的运行时写的这么浅显易懂,我实在是佩服,我会坚定的做你最忠实的读者
    01_Jack:@丁小丁iOS 谢谢支持😄

本文标题:Runtime系列(消息转发)

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