专栏首页一个番茄说浅析为何能通过FDStackView在iOS9以下使用UIStackView

浅析为何能通过FDStackView在iOS9以下使用UIStackView

前几天看到sunnyxx团队的新作FDStackView。大家都知道在iOS9苹果提供了一个新的玩具UIStackView,然而在iOS9以前是没有办法使用的。可通过FDStackView你却可以在iOS9以前的系统上使用UIStackView,更重要的是我们不需要去做任何额外的工作,FDStackView会自动为我们处理好一切。

今天分析了一下是如何实现这个神奇的功能的,在FDStackView.m中嵌入了一段内联汇编:

__asm(
  ".section        __DATA,__objc_classrefs,regular,no_dead_strip\n"
#if TARGET_RT_64_BIT
  ".align          3\n"
  "L_OBJC_CLASS_UIStackView:\n"
  ".quad           _OBJC_CLASS_$_UIStackView\n"
#else
  ".align          2\n"
  "_OBJC_CLASS_UIStackView:\n"
  ".long           _OBJC_CLASS_$_UIStackView\n"
#endif
  ".weak_reference _OBJC_CLASS_$_UIStackView\n"
  );

这段代码的主要作用是在DATA这个segment中暴露了L_OBJC_CLASS_UIStackView这个符号,它指向了符号OBJC_CLASS$_UIStackView(编译器硬编码确定)。

然后在类被成功加载之后会调用FDStackViewPatchEntry,这里面首先判断如果是iOS9的话那就啥也不需要做了。

这里面比较关键的代码在这里:

#if TARGET_CPU_ARM
        __asm("movw %0, :lower16:(_OBJC_CLASS_UIStackView-(LPC0+4))\n"
              "movt %0, :upper16:(_OBJC_CLASS_UIStackView-(LPC0+4))\n"
              "LPC0: add %0, pc" : "=r"(stackViewClassLocation));
#elif TARGET_CPU_ARM64
        __asm("adrp %0, L_OBJC_CLASS_UIStackView@PAGE\n"
              "add  %0, %0, L_OBJC_CLASS_UIStackView@PAGEOFF" : "=r"(stackViewClassLocation));
#elif TARGET_CPU_X86_64
        __asm("leaq L_OBJC_CLASS_UIStackView(%%rip), %0" : "=r"(stackViewClassLocation));
#elif TARGET_CPU_X86
        void *pc = NULL;
        __asm("calll L0\n"
              "L0: popl %0\n"
              "leal _OBJC_CLASS_UIStackView-L0(%0), %1" : "=r"(pc), "=r"(stackViewClassLocation));
#else
#error Unsupported CPU
#endif

这里判断了CPU的指令集,以ARM为例说明。 由于不能将一个32位的常量直接存入一个寄存器中,所以需要分别取它的高16位和低16位存入。 完了之后将pc和%0相加存入%0中,然后将输入保存到stackViewClassLocation。

接着通过runtime的objc_allocateClassPair创建了一个名为UIStackView的类,并在stackViewClassLocation指针所指向的空间中写入新创建的class,然后FDStackView就华丽变身为UIStackView了。

结尾: 由于我本人对汇编也不是很熟悉,只是简单的分析了一下,所以如果有不对的地方麻烦大家不吝赐教共同学习:)

BTW,这样的方式如果是为UIStackView写了category也没办法使用了,因为分类是写在原来的类上面的,暂时还不知道怎么解决。

参考链接: http://www.ethernut.de/en/documents/arm-inline-asm.html http://hailoong.sinaapp.com/?p=125

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 开篇——讲给小白听的比特币

    第一次听到比特币的时候大概是好几年前了,当时第一反应是难不成又出了个什么纪念币或者哪个傻逼国家自己印了新的货币出来。带着好奇心试图去了解清楚到底这是个什么东西,...

    100000798482
  • iOS 开发安全那些事儿

    ​ 随着移动互联网的普及,被越来越多的心怀不轨的人觊觎,也越来越多的安全问题暴露了出来。开发者开发出来的应用被安装在设备上之后,用户并不具有专业的安全知识。...

    100000798482
  • 你知道你用的数字钱包到底是个什么玩意儿么

    有钱就有钱包的需求,那么对应到数字货币也是一样的。然而在比特币等数字货币的世界中,我们使用的数字钱包和传统意义上的电子钱包还是有区别的,他并不是给你开一个户,然...

    100000798482
  • 零日攻击是混合云面临的主要问题

    根据一项新的调查研究,混合云环境特别容易受到 “零日漏洞”(zero-day)的攻击。 “零日漏洞”就是安全漏洞在当天或在24小时内被发现之后立即被恶意利用进行...

    静一
  • ​你可能不太会用的10个Git命令

    如果你不熟悉基本的 git 命令,在阅读本文前可以先参考我之前写的关于 Git 工作流程的文章。

    机器之心
  • 你可能不太会用的 10 个 Git 命令

    本文讨论的是开发人员、数据科学家或产品经理应该了解的各种 Git 命令。我们将了解该如何用 Git 进行检查、删除和整理操作。我们还将介绍如何用 Bash 别名...

    Spark学习技巧
  • 从“陪练”到“赢家”:人机博弈的六十年

    大数据文摘
  • 推荐收藏 | 数据产品经理的书单

    4月23日对于世界文学而言是一个具有象征性意义的日子。1616年的这一天,塞万提斯、莎士比亚、印卡·加西拉索·德拉维加几位大师相继与世长辞。此外,这一天也是其他...

    用户6021891
  • 基于RGW的多媒体处理框架

    业务需要在原有RGW的服务基础上加上对多媒体类资源的处理,比如图片resize、视频转码等。参考过多个厂家的设计,发现对方的多媒体类处理都是在URL里面加上qu...

    用户1260683
  • 算法帝国里的牛人们:布尔

    大数据文摘

扫码关注云+社区

领取腾讯云代金券