资讯专栏INFORMATION COLUMN

深入学习runtime

jerryloveemily / 2571人阅读

摘要:本文的切入点是年的一场线下分享会,也就是分享的。当时他出了一份试题,并戏称精神病院入院考试。我们今天的这篇文章就是从这个试题中的题目入手,来深入的学习。为了兼容老的第一个参数是接收消息的,第二个是见名知意

本文的切入点是2014年的一场线下分享会,也就是sunnyxx分享的objc runtime。很惭愧,这么多年了才完整的看了一下这个分享会视频。当时他出了一份试题,并戏称精神病院objc runtime入院考试。

我们今天的这篇文章就是从这个试题中的题目入手,来深入的学习runtime。

源码版本objc4-750

第一题
@implementation Son : Father
- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

第一行的[self class]应该是没有疑问的,肯定是Son,问题就出在这个[super class]

大家都知道,我们OC的方法在底层会编译为一个objc_msgSend的方法(消息发送),[self class]符合这个情况,因为self是类的一个隐藏参数。但是super并不是一个参数,它是一个关键字,实际上是一个“编译器标示符”,所以这就有点不一样了,经查阅资料,在调用[super class]的时候,runtime调用的是objc_msgSendSuper方法,而不是objc_msgSend

首先要做的是验证一下是否是调用了objc_msgSendSuper。这里用到了clang这个工具,我们可以把OC的代码转成C/C++。

@implementation Son
- (void)test {
    [super class];
}
@end

在终端运行clang -rewrite-objc Son.m生成一个Son.cpp文件。

在这个.cpp文件的底部我们可以找到这么一部分代码

// @implementation Son

static void _I_Son_test(Son * self, SEL _cmd) {
    ((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Son"))}, sel_registerName("class"));
}
// @end

看起来乱七八糟,有很多强制类型转换的代码,不用理它,我们只要看到了我们想要的objc_msgSendSuper就好。

去源码中看一下这个方法(具体实现好像是汇编,看不懂)

OBJC_EXPORT void
objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

可以看出来这个方法第一个参数是一个objc_super类型的结构体,第二个是一个我们常见的SEL,后面的...代表还有扩展参数。

再看一下这个objc_super结构体。

/// Specifies the superclass of an instance. 
struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;

    /// Specifies the particular superclass of the instance to message. 
#if !defined(__cplusplus)  &&  !__OBJC2__
    /* For compatibility with old objc-runtime.h header  为了兼容老的 */
    __unsafe_unretained _Nonnull Class class;
#else
    __unsafe_unretained _Nonnull Class super_class;
#endif
    /* super_class is the first class to search */
};

第一个参数是接收消息的receiver,第二个是super_class(见名知意~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/17231.html

相关文章

  • iOS 进阶必读 - 收藏集 - 掘金

    摘要:深入研究捕获外部变量和实现原理掘金前言是语言的扩充功能,而在和中引入了这个新功能。是由和两位大神在对的开发过程中中所有变换操作底层实现分析上掘金前言在上篇文章中,详细分析了是创建和订阅的详细过程。 深入研究Block捕获外部变量和__block实现原理 - 掘金 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这个新功能B...

    sf_wangchong 评论0 收藏0
  • iOS 进阶必读 - 收藏集 - 掘金

    摘要:深入研究捕获外部变量和实现原理掘金前言是语言的扩充功能,而在和中引入了这个新功能。是由和两位大神在对的开发过程中中所有变换操作底层实现分析上掘金前言在上篇文章中,详细分析了是创建和订阅的详细过程。 深入研究Block捕获外部变量和__block实现原理 - 掘金前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这个新功能Bl...

    szysky 评论0 收藏0
  • iOS 模块分解—「Runtime面试、工作」看我就

    摘要:引导相信对于从事开发人员来说这个名称都不陌生,就像我起初只知道叫运行时,后来知道同样可以像一样访问私有成员变量,还有给类动态添加属性交换方法,还有深入的消息机制的调用流程字典转模型实现归解档以及我们常说的黑魔法是什么是编程中比较难的模块,想 引导 相信对于从事开发人员来说 runtime 这个名称都不陌生,就像我起初只知道「 runtime 叫运行时 」,后来知道 runtime 同...

    Bmob 评论0 收藏0
  • 深入Vue.js从源码开始(一)

    摘要:的源码利用了做了静态类型检查。它包括把模板解析成语法树,语法树优化,代码生成等功能。关于语法树的介绍可见一看就懂的抽象语法树目录包含了的核心代码,包括内置组件全局封装,实例化观察者虚拟工具函数等等。表示构建出来的文件遵循规范。 本系列为慕课网《Vue.js 源码全方位深入解析》课程的学习笔记 认识 Flow Flow 是 facebook 出品的 JavaScript 静态类型检查工具...

    shery 评论0 收藏0
  • 深入Vue.js从源码开始(二)

    摘要:有一点要注意的是,暴露的方法最好不要依赖,因为它可能经常会发生变化,是不稳定的。 从入口开始 我们之前提到过 Vue.js 构建过程,在 web 应用下,我们来分析 Runtime + Compiler 构建出来的 Vue.js,它的入口是 src/platforms/web/entry-runtime-with-compiler.js: 摘选entry-runtime-with-co...

    rainyang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<