转载

Storyboard的爱与恨(上)

尽管现在已经是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的约束

Storyboard的爱与恨(上)

View自身的约束

Storyboard的爱与恨(上)

View与Other View的约束

Storyboard的爱与恨(上)

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

//用代码来实现上图中View与Super View的约束     UIView *superView = self.view;     UIView *subView = [[UIView alloc] init];     NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:superView                                                            attribute:NSLayoutAttributeLeading                                                            relatedBy:NSLayoutRelationEqual                                                               toItem:subView                                                            attribute:NSLayoutAttributeLeading                                                           multiplier:1                                                             constant:15];     NSLayoutConstraint *TrailingConstraint = [NSLayoutConstraint constraintWithItem:superView                                                                          attribute:NSLayoutAttributeTrailing                                                                          relatedBy:NSLayoutRelationEqual                                                                             toItem:subView                                                                          attribute:NSLayoutAttributeTrailing                                                                         multiplier:1                                                                           constant:15];  //topConstraint init... //bottomConstraint init...     [superView addConstraint:leadingConstraint];     [superView addConstraint:TrailingConstraint];     [superView addConstraint:topConstraint];     [superView addConstraint:bottomConstraint];      // 如果是iOS8+ 则使用下面的方式来激活Constraint     // leadingConstraint.active = YES;     // leadingConstraint.active = YES;     // leadingConstraint.active = YES;     // leadingConstraint.active = YES; 

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

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

Storyboard的爱与恨(上)

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

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

Auto Layout Debug

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

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

Storyboard的爱与恨(上)

上图的例子是:我们为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和现有设备的对照表如下:

Storyboard的爱与恨(上)

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

if (IPAD_PORTRAIT)   {     //TODO:modify something portrait } else   {     //TODO:modify something landscape } 

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

- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection                withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator {     [super willTransitionToTraitCollection:newCollection                   withTransitionCoordinator:coordinator];     [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context)      {         if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {             //To Do: modify something for compact vertical size         } else {             //To Do: modify something for other vertical size         }         [self.view setNeedsLayout];     } completion:nil]; } 

在TODO中做相对应Size的事。

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

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

能不能再给力点?

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

Storyboard的爱与恨(上)

能不能再给力点儿?

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

Storyboard的爱与恨(上)

Storyboard的爱与恨(下) ----未完成

原文  http://shengpan.net/storyboard/
正文到此结束
Loading...