美文网首页
Runtime 与 Aspects

Runtime 与 Aspects

作者: Alfred的记录本 | 来源:发表于2018-04-12 16:04 被阅读0次

Runtime 之 isa指针

111.png

1.横向看:实例是对象,类也是对象(类对象),meta类也是对象(原类对象)
这是很重要的一点,希望大家理解,我们这里忽略上下结构,先看左右结构,从左到右的指向就是之前介绍的runtime源码中objc_class结构里isa的指向,Instance指的是我们创建的对象,Subclass(class)就是创建该对象的那个类,注意:创建对象的类本身也是对象,称为类对象,类对象中存放的是描述实例相关的信息,例如实例的成员变量,实例方法。
类对象里的isa指针指向Subclass(meta),Subclass(meta)也是一个对象,是原类对象,原类对象中存放的是描述类相关的信息,例如类方法,在这一过程中,isa的两次指向很像很像,大家注意理解。
2.纵向看:
superclass指针很容易理解,就是按照继承关系向上指的,一直到继承链的最上方。

参考:为什么object_getClass(obj)与[OBJ class]返回的指针不同

实例方法class 和类方法class

  • 类方法是在meta class里的,类方法就是把自己返回,而实例方法中是返回实例isa的类
+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}
Person *obj = [Person new];
    NSLog(@"instance         :%p", obj);
    NSLog(@"class            :%p", object_getClass(obj));
    NSLog(@"meta class       :%p", object_getClass(object_getClass(obj)));
    NSLog(@"root meta        :%p", object_getClass(object_getClass(object_getClass(obj))));
    NSLog(@"root meta's meta :%p", object_getClass(object_getClass(object_getClass(object_getClass(obj)))));
    NSLog(@"---------------------------------------------");
    NSLog(@"class            :%p", [obj class]);
    NSLog(@"meta class       :%p", [[obj class] class]);
    NSLog(@"root meta        :%p", [[[obj class] class] class]);
    NSLog(@"root meta's meta :%p", [[[[obj class] class] class] class]);
instance         :0x135d50810
class            :0x1008d6b58
meta class       :0x1008d6b80
root meta        :0x1a0b6c048
root meta's meta :0x1a0b6c048
---------------------------------------------
class            :0x1008d6b58
meta class       :0x1008d6b58
root meta        :0x1008d6b58
root meta's meta :0x1008d6b58
  • 从打印结果我们能看到,类也是对象,meta类也是对象,都占有一块内存,
  • 用object_getClass()验证了我们Class、Object结构模型理论是对的,我们这里特意的打印了root meta class 的isa,发现果然指向是自己(0x1a0b6c048)
  • 我们发现调用class方法的方式不能得到isa的指向链,但是第一次调用是正确的(class的输出都是0x10ae0e178),为什么?原因就是上面贴出来的class源码中,我们第一次调用的class是实例方法,会返回isa的类,但是第二次开始调用的就是类方法,返回的是本身,所以还是0x10ae0e178,以后无论怎么调用都是执行的类方法,返回的都是本身,所以,用class方法是得不到isa指向链的。

Note: 其实这里的难点就在于对 .class 和 object_getClass 的区分。
.class 当 target 是 Instance 则返回 Class,当 target 是 Class 则返回自身
object_getClass 返回 isa 指针的指向

Runtime 之一些方法

Method targetMethod = class_getInstanceMethod(klass, selector);//函数的实例
IMP targetMethodIMP = method_getImplementation(targetMethod);//函数的实现

消息转发机制

消息转发机制

Aspects

  • aspects 流程
    1)为对象增加一个关联关系:aspects__viewDidLoad关联内容是 aspectContainer
    2)由对象 和 sel 生成一个identifier
    3) 把identifier增加到container中
    4.1)生成类_Aspects_AspectsViewController, _Aspects_AspectsViewController是 AspectsViewController的子类。
    4.2)修改_Aspects_AspectsViewController的forwardInvocation函数的实现为_ASPECTS_ARE_BEING_CALLED_
    4.3)_Aspects_AspectsViewController增加方法__aspects_forwardInvocation,__aspects_forwardInvocation的实现为原forwardInvocation函数的实现。
    4.4)修改对象原类,isa 指针由AspectsViewController 变成 _Aspects_AspectsViewController,。
    5)给类_Aspects_AspectsViewController中增加方法aspects__viewDidLoad 其实现时 原viewDidLoad的实现
    6)给类_Aspects_AspectsViewController 中的方法 viewDidLoad 的实现修改为_objc_msgForward

  • 我们以在ViewControler的viewWillAppear:方法之后插入一段代码为例,来讲解hook前后的变化, 在没有hook之前,ViewController的SEL与IMP关系如下


    222.png
333.png

然后,我们再来看看hook后,一个viewWillAppear:的实际调用顺序:

  • object收到selector(viewWillAppear:)的消息
  • 找到对应的IMP:_objc_msgForward,执行后触发消息转发机制。
  • object收到forwardInvocation:消息
  • 找到对应的IMP:ASPECTS_ARE_BEING_CALLED,执行IMP
  • 向object对象发送aspects_viewWillAppear:,执行最初的viewWillAppear方法的IMP
  • 执行插入的block代码
  • 如果ViewController无法响应aspects_viewWillAppear,则向object对象发送__aspects_forwardInvocation:来执行最初的forwardInvocation IMP
  • 所以,Aspects是采用了集中式的hook方式,所有的调用最后走的都是一个C函数ASPECTS_ARE_BEING_CALLED

参考
消息转发机制与Aspects源码解析

相关文章

  • Runtime 与 Aspects

    Runtime 之 isa指针 1.横向看:实例是对象,类也是对象(类对象),meta类也是对象(原类对象)这是很...

  • runtime系列文章总结

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

  • Aspects源码解读与runtime

    开篇 由于近期在搞优化无侵入埋点,在github上发现了一个基于swizzling method 的轻量级开源框架...

  • 从 Aspects 来看 Runtime

    用 OC 开发 iOS 应用的人都知道 OC 是一门动态语言。我们能够在运行时通过 Runtime API 获取并...

  • iOS runtime 机制

    OC 当中,runtime 可以说是重中之重,很多的第三方SDK,诸如: Aspects、JSPatch等,都是利...

  • Mach-O文件格式分析

    最近用纯Swift参照非常知名的Aspects写了个Aspect,是基于Runtime进行方法交换,正好之前听说过...

  • Aspects改进尝试

    背景 一个库:Aspects两篇文章:面向切面编程之 Aspects 源码解析及应用消息转发机制与Aspects源...

  • Runtime最佳实践之Aspects

    闯荡开发那些街有谁不识Runtime但却只闻黑魔法从未项目运乾坤 一、前言 使用Objective-C开发iOS项...

  • iOS打点

    1.iOS 关于统计打点2.使用runtime 实现iOS自动打点统计3.iOS 统计打点那些事4.Aspects

  • Runtime窥探 (六)| AOP与Aspects核心源码

    前言 如何把这个世界变得美好?把你自己变得更美好 我们这篇博客继续来介绍Runtime在开发中的实际应用,通过开源...

网友评论

      本文标题:Runtime 与 Aspects

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