用 YogaKit 实现 Xib

前言

本文要讲述的是如何使用 YogaKit 提供的 FlexBox 布局能力来实现类似 Xib 的功能(Xib 布局是 AutoLayout)。

GitHub 地址:https://github.com/danleechina/YogaLayout

构想

Xib(StoryBoard) 的原理

先说一下 Xib(StoryBoard) 的原理:

  1. 在 Xcode 中使用 Interface Builder 来构建一个界面或者视图。这个过程其实就是创建、修改 XML 界面描述文件。右键 xib 类型的文件,在 Open As 中选择 Source Code,可以看到 xib 类型的文件其实就是苹果用自己定义的一套 XML 来描述视图
  2. 编译的时候,IDE 会解析项目中所有的 xib 类型的文件,根据苹果自己的一套规则(我们不可知),生成一个可归档的类,然后将该类归档生成一个 nib 类型的二机制文件。如果项目中有使用 xib 的话,解压打包出来的 ipa,就会看到这些 nib 类型的文件,这些文件就是 IDE 在编译时候解析生成的。
  3. 运行时,当需要展示一个 xib 描述的视图时,iOS 系统则会去加载 nib 文件得到之前编译时候生成的归档类实例,根据这个实例生成视图需要的所有子视图,并设置这些子视图的约束和属性
  4. 最后如果有设置 IBOutlet 的话,会将生成的视图赋值给其 owner。

想要了解 xib 更加深入的内容可以查看我之前翻译的一篇文章:macOS 和 iOS 中 Nib 文件实现原理以及最佳实践

可以看到,要实现类似 Xib 这样的工具需要如下一些条件:

  1. 一套类似的 XML 来描述视图的组成(比如某个视图有哪些子视图,它又是那个视图的子视图),配置视图的属性(比如配置 label 的 text 属性),以及定义视图之间的布局(比如使用 autolayout)
  2. 出于性能考虑,可以提前解析该 XML,生成类似 nib 的类
  3. 运行时解析该 XML(如果在编译阶段提前解析了,则不需要),将 XML 中视图的组成,视图的属性,视图的布局给提取出来,动态生成相应视图,并配置其属性、子视图、父视图、布局等
  4. 如果 XML 描述的文件有指定的 Outlet 的话,则将其赋值给相应的类

构想实现

定义 XML 描述视图规则

<UIView id="gradeTipView" style="alignItems:center;justifyContent:center; marginLeft:12;marginRight:8">
    <UILabel id="gradeNameLabel" style=""></UILabel>
    <StarBarView id="starBarView" style=""></StarBarView>
</UIView>
  1. 在这里,每一个 XML 标签名字是视图类的名字,以便运行时通过 NSClassFromString 得到类对象,再通过类对象生成该视图类的一个实例
  2. 每一个 XML 标签有一些属性,比如上面的 id 和 style。id 的作用等同于 IBOutlet,将动态生成的类实例赋值给其 owner,style 的作用是描述布局,然后将其设置到 YogaKit 中。还可以添加别的属性,比如说如果是 UILabel 的话设置 text="我是文本" 来描述其 text 属性,代码中使用 KVC 来实现
  3. style 属性的值指定多个的时候需要通过分号隔离,键值对通过冒号隔离
  4. 每一个 XML 标签会包含其他 XML 标签,比如上面 UIView 包含一个 UILabel 标签,一个自定义的 StarBarView 标签,意思就是说该 UIView 有两个子视图,第一个是一个 UILabel,第二个是自定义视图 StarBarView
  5. 为了简单,每一个类似该 XML 的文件只能有一个根标签

比如不能出现下列场景:

<UIView></UIView>
<UILabel></UILabel>
<UIButton></UIButton>

在这里,根标签有三个,第一个 UIView,第二个 UILabel,第三个 UIButton,这个情况目前不被允许(对 xib 了解的可能会知道从 nib 获取视图对象会返回一个数组,就是说 xib 可以有多个根层级的视图)

实现细节

  1. 如何解析 XML?为了简单起见我直接使用了苹果官方处理 XML 的类 NSXMLParser。实现代理方法,调用 parse 函数即可完成 XML 解析。有一点要注意,调用 parse 函数是同步的,也就是说当 parse 函数返回时,如果实现了代理方法,则代理方法均已经被使用过了。
  2. 解析 XML 的结果是一个树形的数据模型,该树形结构的每一个节点包含视图类的名字,视图的属性(包括视图的布局信息),子视图信息,以及父视图信息(没有父视图意味则是根节点)
  3. 从树形数据模型的根节点开始动态生成该视图的实例,并配置实例的属性,子视图信息和父视图信息等
  4. 在 XML 中有时候定义一个视图的宽高时会需要屏幕宽高的信息,并做一下简单表达式的计算,比如视图的高时屏幕的高的 2/3,这里做表达式计算的时候可以使用 NSExpression 来处理。
  5. 用 Swift 编写的视图类使用 Objective C 来动态生成的时候,需要加上当前二机制文件的名字,这个需要注意

未来

  1. 支持动态设置文本、颜色、图片、CGRect(结构体) 等属性
  2. 简化 Swift 中 Outlet 的设置
  3. 考虑能否去掉 Outlet,使用者传入数据,数据和视图能够双向绑定
  4. 支持 Debug 模式下不重新编译,仅需更改 XML 文件即可更新视图布局

参考

  1. XML 教程
  2. Flex 布局教程:语法篇
  3. Yoga Kit
  4. macOS 和 iOS 中 Nib 文件实现原理以及最佳实践
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容