iOS 开发技术选型之搭建 UI:代码手写 vs. Xib vs
在开发一个 iOS 应用之前,我们一定会问这样一个问题:我应该用哪种方式搭建界面呢,代码手写,Xib 还是 Storyboard。当我们手握好几个工具的时候,很容易犯选择困难症。即使是一个合作默契的团队,成员们也难免有不同的偏好,难以形成一致的结论。所以我们有必要去探索每个工具的优缺点和各自最适合的场景,以期得出一些最佳实践,提高开发效率和应用质量。
代码手写
有一类程序员特别喜欢用代码控制一切。他们觉得既然 Xibs 和 Storyboards 能做和不能做的都能通过代码手写完成,那为什么还要多依赖一个工具呢。直接代码手写不是更专注更高效吗。还好我不属于这类狂热分子,所以我能更客观地看待。
优点
- 开发者能更好的理解背后发生了什么,也拥有更多的控制权,所以 Xibs 和 Storyboard 完不成的通过代码一定能完成。
- 多人合作时在版本控制上的优势,即使发生了合并冲突,因为是纯代码,所以更易于手动解决。也便于追踪改动。
- 有很好的重用性。有时候需要封装一些控件在项目里多处使用或提供给其它开发者使用,用代码手写是最好的方式,同时也便于后续的修改。
缺点
- 速度慢,效率低。代码手写意味着所有的初始化设置都需要自己写,势必花费更多时间。另外由于无法可视化地为 UI 元素布局,在开发过程中也会浪费很多时间在调试上。
- 增加了维护难度。也许过了一段时间再看所写的代码或是新来的成员要读代码,都有可能被那些诡异的数字给弄懵的。
Xibs
在我刚开始学习 iOS 开发的时候,还好有 Xib 可以选择。通过拖拽就能将各种控件摆放在正确的位置,在触摸板上点点就能设置各种属性,这种可视化的方式无疑让我很有兴趣继续学习去。但和代码手写一样,各有优缺点。
优点
- 可视化,包括添加控件和设置属性,配置 IBOutlet 和 IBAction,支持 Autolayout,支持 Size classes。因此能够快速搭建界面,减少代码,省下大量开发和调试的时间。也使得 ViewController 可以更少地关注搭建 UI 的事。
- 重用性。通常是一个 Xib 文件对应一个 ViewController,如果多个 ViewController 用到相同的元素组合,那我们就可以把这部分提出来放到专门的 Xib 文件里,用一个自定义的 View 去管理它们。比如会被重用的自定义的 TableViewCell 也会这么处理。
缺点
- 多人协作时版本控制上的劣势,合并冲突时不易处理。虽然在 Xcode5 之后 Apple 优化了 xib 文件的格式,变得更易读易追踪,但还是不如纯代码那么容易处理。
- 无法完成一些更复杂的,动态的布局。通常需要在 xib 中先设置好 Autolayout 约束,再在代码中做一些动态的处理。
- Xib 中属性设置可以被覆盖,导致在后期维护中面对一些诡异的界面问题时却无法快速的找出原因。这点需要我们在开发过程中约定好尽量不要在代码中修改属性。
Storyboards
Apple 从 Xcode5 开始将 Storyboard 作为新建项目的默认配置,可见它强力推广 Storyboard 的决心。Storyboard 顾名思义,重点在于将多个场景关联起来展示一个连贯的故事。在 Xcode 里,可以看成把一组 ViewController 对应的 Xib 文件放到一个文件中,并配置好它们之间的转场方式。所以 Storyboard 和 Xib 的优缺点会有重合。
优点
- 可视化,除了前面 Xib 那段中提到的快速搭建界面意外,Storyboard 还增加了各个 ViewController 之间的转场关系,使得开发者尤其是新加入的开发者能更容易更清晰的整理整个应用的流程和交互。基于这一点我们甚至还可以不写代码直接拿来做简单的原型设计。
- 支持在 TableView 中直接添加 Cell,包括动态和静态两种类型。当一个 TableView 有很多不同样式的 Cell, 或者是固定的 Section 和 Cell 的时候,这个特性会提供很大的便利。
缺点
- 文件大,加载慢。一般情况下很容易会把所有的 ViewController 放在同一个 Storyboard 里,导致文件很大,打开的时候需要加载几十秒。可尝试拆分 Storyboard 缓解这个症状。
- 多人协作时容易产生合并冲突。一方面多个成员可能对同一个 Storyboard 进行修改,另一个方面 Xcode 在打开文件的时候可能会根据版本自动做一些修改,这些都给合并代码制造了麻烦。可通过拆分 Storyboard 达到每个成员只负责其中一个
- 不能单独存在自定义的 View。因为 Storyboard 更强调 ViewController 之间的关系,也就是整体的流程,所以不允许单个 View 的存在。这也是 Xib 文件该跳出承担责任的时候了。
- 触发 Segue 和数据传递的分裂。有时候我们需要在 ViewController 之间传递数据,但是如果用常规的 Storyboard 的流程的话需要先通过
performSegueWithIdentifier:sender:
触发然后再在prepareForSegue:sender:
方法中获得目标 ViewController 再对其属性进行赋值。使得本应该连贯的过程被分裂了。
总结
在了解了每种方式的优缺点后,我们才可以根据不同的应用场景选择更合适的方法。在这个问题中,这几个选项不是排他的,而是可以相互合作来提升开发效率和应用质量。
总体来说可以根据应用的规模来决策:
- 小型:请毫不犹豫地使用 Storyboard 吧。可视化,速度快。把所有界面都放在一起,让人有一种君临天下的感觉。
- 中型:主体用 Storyboard,一些需要重用的 View 用单独的 Xib,比如 TableViewCell。
- 大型:将应用分成不同的模块,每一个模块用一个单独的 Storyboard。比如基于
UITabBarViewController
的应用可以按照 Tab 来分成若干个 Storyboard。Apple 还在 iOS 9 引入了 Storyboard references 帮助开发者重构以获得更好的模块化。
另外,代码手写的方法也不是没有用用武之地,那些布局复杂,动态性高的 View 更适合通过代码来搭建。
最后再说一句,随着现代 IDE 的发展,越来越多的底层实现细节被隐藏起来,但作为开发者,我们还是有必要去探索背后的真理,才能更从容地面对各种意料之外的问题。