前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅析为何能通过FDStackView在iOS9以下使用UIStackView

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

作者头像
100000798482
发布2018-08-20 17:06:26
7610
发布2018-08-20 17:06:26
举报
文章被收录于专栏:一个番茄说一个番茄说

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

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

代码语言:javascript
复制
__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的话那就啥也不需要做了。

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

代码语言:javascript
复制
#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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015.10.12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档