美文网首页APP & program
iOS Runtime之方法查找

iOS Runtime之方法查找

作者: 谢二九 | 来源:发表于2022-06-23 15:14 被阅读0次

Runtime系列导读

介绍

OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行。
OC的动态性就是由Runtime来支撑和实现的,Runtime是一套C语言的API,封装了很多动态性相关的函数平时编写的OC代码,底层都转换成Runtime API(主要是objc_msgSend和objc_msgSendSuper)进行调用。
我们可以利用Runtime做以下具体场景应用:

  • 关联对象(AssociatedObject)给分类添加属性;
  • 遍历类的所有成员变量;
  • 交换方法实现;
  • 利用消息转发机制解决方法找不到的异常问题

方法存储

实例对象与类的关系

定义

科普下实例对象(instance)、类(class)、元类(meta-class)。

  • 类在面向对象编程中是一种面向对象计算机编程语言的构造,描述了所创建的对象共同的属性和方法。
  • 实例对象是根据某个类创建的对象。
  • 元类:是一种实例是类的类。

综上总结,类是实例对象的描述,元类是类对象的描述。

模型

实例对象的存储结构(以NSObject实例对象举例):

struct NSObject_IMP{
  Class isa;
}

其中,isa是指向NSObject类的指针。

类对象的存储结构

struct objc_class {
    Class _Nonnull isa;
    Class _Nullable super_class;
    struct objc_ivar_list * _Nullable ivars;
    struct objc_method_list * _Nullable * _Nullable methodLists;
    struct objc_cache * _Nonnull cache;
    struct objc_protocol_list * _Nullable protocols;
    ...
}

其中,

  • isa是指向元类的指针
  • super_class是指向父类的指针
  • ivars是指向成员变量的指针
  • methodLists是指向方法列表的指针
  • cache是指向方法缓存的指针
  • protocols是指向协议的指针

关系

通过源码分析,可以确认实例对象、类和元类是以下关系:

  • 实例对象的isa指向类
  • 类的isa指向元类
  • 元类的isa指向基类的元类
  • 类的superclass指向父类。如果没有父类,superclass指针为nil
  • 元类的superclass指向父类的元类。基类的元类的superclass指向基类
  • 实例对象调用实例方法,是通过isa找到类,如不存在则通过superclass找父类
  • 类调用类方法,是通过isa找元类,如不存在则通过superclass找父类

消息发送

消息发送从类对象或者元类的方法列表缓存和方法列表中查,没有则通过super指针逐级向上,有则缓存并调用。

动态方法解析

开发者可以实现以下方法,来动态添加方法实现:

  • +resolveInstanceMethod:
  • +resolveClassMethod:

动态解析过后,会重新走“消息发送”的流程,“从receiverClass的cache中查找方法”这一步开始执行。

消息转发

  • a转发给谁处理 - (id)forwardingTargetForSelector:(SEL)aSelector{}
  • b获取方法签名 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{}
  • c自定义转发逻辑 - (void)forwardInvocation:(NSInvocation *)anInvocation{}

延伸问题

  • 方法模型结构
  • 方法缓存什么场景下会清理
  • NSProxy用法

相关文章

网友评论

    本文标题:iOS Runtime之方法查找

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