Storyboard 的爱与恨

520 查看

54.jpg

 

尽管现在已经是Apple将Storyboard整合进Xcode中的第四个年头,大家对于Storyboard的评价仍然褒贬不一。有早期就选择转向Storyboard用于UI开发的国内业界领头人物,也有创建项目就立马删除Storyboard的大牛。我经历过纯代码布局,同时也在多个多人合作项目中使用Storyboard开发界面。在初期绕过各种坑后,Storyboard将会是快速构建UI界面的好帮手,特别是在现如今设备分辨率与尺寸日益增加的情况下,它可以帮助工程师们节约大量的界面代码书写时间。Storyboard存在的一大意义在于为UI提供了可视化开发方式,另一方面提供了一种更好的MVC的View层实现方式,让你的ViewController代码更简洁。当然,Storyboard的不足仍然不可忽视,错误的难以定位经常让刚上手的开发者们手足无措,相比于代码更不容易阅读的XML源文件所导致多人合作中的冲突不易解决等问题仍然有待完善。本文从各个方面介绍一下Storyboard,分享一下Storyboard的一些使用心得。

历史

1986年Jean-Marie Hullot发明了IB(Interface Build–Storyboard的前身),并且和Macintosh的工具箱无缝融合,这一工具被Denison Bollay发现了。第二年, Denison Bollay带着Hullot和他的IB到NeXT,将IB演示给Steve Jobs看。老乔立意识到了IB的价值,并将其纳入到了NeXTSTEP中。之后Steve 带着NeXT的技术结晶(当然也包括IB)重新回归Apple,并将之整合到了Apple的体系中。2008年第一代iPhone SDK发布的时候,IB就已经捆绑在其中。到了Xcode4,Apple更是直接将其集成进IDE里。随后随着不断地改进,更新,演变,最终变成了我们今天所看到的Storyboard。从某种角度来说,Storyboard也是老乔留给我们的众多礼物之一。

故事板能做什么

故事板主要为我们提供了以下的功能:(这些功能都是可视化的)

  • Auto Layout
  • Size Classes
  • Secnce的跳转
  • 代码可视化

Auto Layout

自动布局颠覆了之前直接操作Frame的布局方式,从思考View应该在哪个位置,变成了考虑在特定条件下,View的所处的位置需要满足哪些条件。通过这些条件来确定View的Frame。自动布局在实际应用中大体上可以将分为三组:

View与Super View的约束

QQ截图20160224113505.png

View自身的约束

QQ截图20160224113548.png

 

View与Other View的约束

QQ截图20160224113613.png

假如我们需要在代码中使用自动布局可以使用 Visual Format Language或者NSLayoutConstraint的简单工厂方法来生成约束,然后添加到View上。我们来看一个例子:

 

是不是一大团乱糟糟的代码?Visual Format Language用起来更加令人崩溃。好在业界已经有比较好的代码自动布局的第三方解决方案。但是仍然会有大堆的简单界面布局代码残留在你的代码中。

为了让你的生活更轻松(也为了让代码更清爽),Storyboard就包含了非常优雅的可视化自动布局解决方案。以上一切,在Storyboard中都被浓缩成了两个按钮(下图红圈中的椭圆按钮)。

1111.png

  • 红框1:为被选中View和离他最近的View(可能是SuperView,也可能是另一个同层级的View,看哪个离它更近)添加Leading、Training、Top、Bottom四个属性约束。
  • 红框2:为View添加自身宽和高约束
  • 红色椭圆左侧按钮:当选中多个View时,为多个View添加约束

只需要点击几下鼠标,Storyboard就可以帮你轻松完成视图布局。

Auto Layout Debug

使用代码来对Auto Layout布局的另一个缺点在于debug的困难。当添加了多余的约束,往往只能在运行时才能发现错误。同时,要寻找出是哪一行代码添加了错误的约束也比较费力(往往连控制台都没有错误输出)。

而Storyboard却为此提供了非常友好的静态检查。主要针对View的约束、布局提供警告和Error,甚至是解决方案。

-----2016-02-19-16-30-51.png

上图的例子是:我们为Label添加了多余的约束,Storyboard用红色标记出冲突的约束,并给出修改建议:删除其中一个约束以保证约束的正确性。是不是很友好? :)

Size Classes

Apple 与iOS 8推出了Size Classes的概念。意在解决因设备尺寸造成的适配问题。Size Classes通过将界面的宽度和高度抽象为正常和紧凑两种概念,通过合理的组合,可以将现有设备(以及未来将要出现的设备)划分到不同的Size中。因此,无论是代码还是界面布局,只需要针对Size进行,而不用再拘泥于分辨是iPhone还是iPad,是横屏还是竖屏的问题了。Size Classes的推出是具有前瞻性的,无论是Apple Watch还是iOS 9推出的的iPad 分屏模式,都可以用Size Classes完美解决适配的问题。

Size Classes和现有设备的对照表如下:

QQ截图20160224114047.png

在之前,我们要对横屏竖屏的界面进行区分,代码一般是这样的:

在Size Classes时代,Apple引入了一个新的类UITraitCollection来封装水平和垂直方向的Size信息。现在我们通过代码来改变界面是这样的:

在TODO中做相对应Size的事。

可以想见的是,仍然会有非常多的布局代码占据着你的源文件。但在Storyboard中,一切变得异常简单。

使用Size Classes,我们只需要选择相对应的size,在那个Size下进行布局。运行时,就会根据设备的尺寸,自动地展示相对应Size的布局。比如iPhone竖屏就展示width Compact height RegularSize下的信息。当手机横屏,系统会自动添加一个过渡动画(虽然有点生硬),并转到width Regular height Compact的Size。这一切不需要一行代码。

能不能再给力点?

Sure.有这么一种情景:iPhone横屏下,拥有一个avatarView,竖屏下拥有一个相同的avatar View。这种情况下我们只需要在一个Size中完成这个View,然后在Storyboard的attributed inspector中做一些勾选,将其”install”进相对应的Size中,就可以达到复用的目的。如果有差异,则在对应的Size中定制即可。(如下图)

QQ截图20160224114232.png

能不能再给力点儿?

Of Course!除了View,约束也可以不同Size配置不同。最厉害的是,图片文件也可以根据Size来区分。我们只需要对.xcassets文件勾选Size Classes,就可以为不同Size配置不同图片.这意味着,在同一个安装包下,通过Size Classes,我们甚至可以为横屏iPhone和竖屏iPhone做出完全不同的App!

QQ截图20160224114320.png

Scene的转场

如我们所料,Storyboard也可以通过可视化的操作来实现Scene的转场。

故事板的转场有两种,可以分为手动触发和自动触发。自动触发完全由Storyboard实现,而手动触发则需要配合代码。前者简单易用,后者适用于配合业务逻辑,进行不同转场的触发。自动触发的转场非常简单,我们只需选择一个UIControl(比如UIButton),按住Control+左键,拖线至目标Scene,选择Action类型,即可在触发UIControl的某些事件的时候,自动执行转场。

ooooo-1.gif

例如利用UIButton转场,实际上是在触发TouchUpInside事件时执行。这一简单的操作实际上相当于如下代码: