在 iOS 上面开发界面,需要创建视图、配置界面、视图分层等等很多步骤,也就不可避免的需要书写 N 多的代码。这还仅仅是界面设计,除此之外,完成 controllers 的回调、控制内部事务在界面上的显示效果、界面的操控和内部事务的联系等等多方面的事情都需要手动解决。即便是界面很简单的 App,如果存在这种复杂的双向数据流的关系,那么代码也会变得很复杂很容易出错。Qt 的信号、槽和 iOS 的 Target-Action 机制其实也是很容易实现这种双向数据流的关系,但是没有办法解决界面和事务之间的联系,也有很多其他的问题:性能、测试等。
这些问题曾经困扰了我们多年。News Feed 是有着复杂的列表样式外观的 iOS 软件,由许多的 Row Type 组成,每一个 Row 都有各种各样不同的很烦的界面样式和交互方式,这个就很坑了。每次维护这个东西都像是在清理厕所,尤其是它的功能还在不断增加,它的代码在不断变多,版本迭代速度快到你都没办法直到每天都到底增添了什么新代码,上司还要拿着报告说“你这个软件太慢了,影响用户体验,给你三个小时把这个 App 的速度提高 80%”。
为了解决这一挑战性的问题,我们从自己的 ReactJS 得到启发,把很多具体的东西抽象出来,做出一个功能性的、响应式编程模型的 iOS 原生 UI 框架 ComponentKit,目前 News Feed 在应用这个框架。
ComponentKit 使用功能性和声明性(declarative)的方法来进行创建界面,和以往不同的是,ComponentKit 使用单向数据流的形式从 不可变的模型 映射到不可变的组件来确定视图的显示方式。ComponentKit 的 declarative 看上去和 declarative UI(QML) 差不多,其实差得远。QML 更偏向于 UI 设计的描述性,而 ComponentKit 则是做好基本 UI 和事件之间的联系,让事件设计和 UI 设计可以分开单独完成。
内在决定外在,组件的功能和内部的层次决定了用户界面该如何规划,界面的规划决定了 UI Kit 的元素层次结构的设计。
传统做法的结果是大部分时间都被浪费在 UI 该如何实现,ComponentKit 却可以让你把时间都用在在 UI 该怎么设计上面。
例如,传统的 iOS 开发中,为了开发一个带有 header、text 和 footer 的视图,需要以下步骤:
但是 ComponentKit 不一样,ComponentKit 是一种描述性的开发包:你只需要提供你希望得到什么便能得到什么,而不和传统的 iOS 开发一样,再去一个一个地创建视图、修改视图样式、添加视图、添加约束条件。如图所示,想要得到这个布局,只需要使用描述性的语言描述“我想要一个 header 组件,一个 text 组件,一个 footer 组件,他们的宽度相同,从上到下排列在一起”。单单从这点来看,和 QML 相比,ComponentKit 更类似于 Bootstrap:提供已经完成的组件,你只需要决定组件如何摆放,便可轻松地开发出 UI 界面。
ComponentKit 已经完全把如何渲染 UI 的事情抽象出来,程序员完全可以不去考虑具体是如何实现渲染的,也不用去考虑界面渲染该如何优化。ComponentKit 使用后台线程进行界面布局,也实现了智能组件重用,你完全可以不去考虑界面导致的内存泄露问题。ComponentKit 不仅仅可以极大地提高开发效率,界面响应速度和软件的运行效率也会有极大地提升。
ComponentKit 极大地提升了 News Feed 的 UI 响应速度和稳定性,也让整个软件的内部编码更容易理解。ComponentKit 达到了如下的目标:
引入了 ComponentKit 之后,我们能够维护更少的代码,有更少的 bug 需要修复,有更大的测试覆盖率:我们现在可以有更多的时间做羞羞的事情了
ComponentKit 已经在生产环境的 News Feed 上用了六个月,我们觉得可以一直用下去。现在将 ComponentKit 开源,让整个 iOS 开发者社区的人都有 Facebook 的生产效率,也都能和 Facebook 一样做出高性能的 App。很希望你也能在你的开发环境中使用 ComponentKit,然后给我们反馈。
我们重新定义了如何在 iOS 上开发界面,希望你也能用 ComponentKit 开发出更优雅的 App。
ComponentKit 已经在 CocoaPods 中可用了,只需要在 Podfile 添加如下代码即可:
pod 'ComponentKit', '~> 0.9'
pod try ComponentKit
原文:Introducing ComponentKit: Functional and declarative UI on iOS