使用 Interface Builder 兼容 iOS6 和iOS7

jopen 10年前

当你在更新你的App到iOS 7的平台时遇到最大的挑战之一就是确保不要遗忘那些还在使用iOS 6平台的用户,在此我们提供一些建议使你的App应用在iOS 6和iOS 7上同时保留视觉吸引力和技术功能.

使用 Interface Builder 兼容 iOS6 和iOS7
此图为Interface Builder中顶部和底部布局指南

设置正确的Interface Builder Storyboard 或者正确设置XIBs文件,对于iOS 6 和iOS7的开发大有帮助,使得开发更加容易。我们的第一个建议是为全部的UIViewController创建Storyboard, UIViewControl是合成的或者是跨越整个屏幕高度的控制试图(Control Views).如果你正在做的项目是使用XIBs文件开发的,而没有使用Storyboards,那么Storyboards可以尽可能的简化为带有视图容器(View Container)的“UIViewController",将来你可以从NIB文件加载。我们这样建议的主要原因是这样操作你可以获得访问在Interface Builder中顶部和底部布局指南的权限。

使用 Interface Builder 兼容 iOS6 和iOS7

Interface Builder中”View as“ 配置,这个设置是每个文件(NIB 或者Storyboard)的基础设置。

另外,我们还建议您把所有的XIBs和Storyboard中的 View as 设置为 iOS 7 and Later,这种设置方式将更加容易降低未来的iOS 6的支持,此外,如果您没有使用自动布局,那么就会更加容易更加直观的使用iOS 6/7 Delta 。

调整状态栏

在iOS 7中状态栏后面的区域变为有用的屏幕空间。因此iOS 7的窗口比iOS6要高出20个点,这就导致了在iOS 7中屏幕顶部的内容显示在状态栏的下面,调整View可以使用或者避免iOS 7中额外的空间导致在iOS 6中的错位

使用 Interface Builder 兼容 iOS6 和iOS7            使用 Interface Builder 兼容 iOS6 和iOS7

iOS 7-内容显示在状态栏下面             iOS 6 内容显示在屏幕外面

如果你的项目没有使用自动布局(Auto Layout),那么可以通过Spring,Struts以及iOS 6/7 Deltas来解决因为iOS 6/7差异导致的状态栏的问题。为了避免内容显示在状态栏下面,仅需简单的把内容移到下面,不管怎样都需要移动几个点来得到状态栏下面的内容。然而,这也同时会导致iOS 6的内容往下移,这显然不是我们所期望的,因为这个内容在iOS6中原本不在状态栏的下方。为了解决这个问题,我们可以通过设置iOS 6/7 Delta来解决,设置一个负值在Y Delta等同于在iOS中向下移动几个点。 比方说,我们在iOS 7中向下移动内容20点,那么我们需要把Y Delta设置为 -20。为了把靠近屏幕底部的内容放置到屏幕底部相对位置,使用正确的Sping,Struts配置会更加容易更加可靠,而不是使用iOS 6/7 Deltas。同理而言,我们可以使用相似的方法调整需要跨越整个屏幕高度的视图(Views)。可以通过在Storyboard 或XIB中调整高度或者起始原点来获得类似iOS 7的大小和位置,以及在Delta中使用Y值或高度设置,结合Sping 和Struts来解决iOS 6中的大小和位置的问题。

以下,提供了简单的范例,使用两个图片Views(一个在屏幕顶部,一个在屏幕底部)

使用 Interface Builder 兼容 iOS6 和iOS7            使用 Interface Builder 兼容 iOS6 和iOS7

Interface builder 设置                               Interface Builder设置

持续保持顶部的UIImageView在状态栏的下方   防止UIImageView离开屏幕底部 

如前所述,假设你正在使用Storyboard,简单的使用由Interface Builder提供的顶部和底部布局的向导,那么自动布局可以更加简单的解决由状态栏差异造成的问题。如果你设置你的顶部和底部的NSLayoutConstraint 是相对于顶部和底部的布局向导(而非root view的顶部和底部),那么在iOS 6和iOS 7中,iOS将自动的做出必要的调整来使得所有信息都显示在屏幕上并且露出状态栏。如果你不能使用Storyboards,你将可能需要通过代码来访问顶部和底部的布局向导。

下面是和以前一样的例子,但是不同于先前,下面是通过使用自动布局和NSLayoutConstraint 中设置顶部和底部相对性来解决这个问题

使用 Interface Builder 兼容 iOS6 和iOS7

相对的在UIImageView的顶部约束(constraint)中设定 Top Layout Guide

使用 Interface Builder 兼容 iOS6 和iOS7

相对的在UIImageView的底部约束(constraint)中设定 Bottom Layout Guide

现在,无论使用Struts,Spring还是iOS 6/7 Dletas又或者使用自动布局和顶部底部布局向导,所有信息都可以被正确的在iOS 6 和iOS 7中显示。

使用 Interface Builder 兼容 iOS6 和iOS7                     使用 Interface Builder 兼容 iOS6 和iOS7

在Interface Builder 调整后的iOS 7界面      在Interface Builder调整后的iOS 6界面

 使用iOS 7半透明的UINavigationBar调整UINavigationController

使用 Interface Builder 兼容 iOS6 和iOS7

Interface Builder中UINavigationBar 的半透明设

当用Interface Builder同时支持iOS 6和iOS 7中遇到的最常见的挑战是为iOS 7设置UINavigationControllerUINavigationBar为半透明,将UINavigationBar设置为半透明会对你的视图(Views)有非常大的影响,并且需要你做出一些改变。

使用 Interface Builder 兼容 iOS6 和iOS7

Interface Build在Extend Edges(边界扩展)中的设置

如果在一个UIViewController里把Extend Edges设置为Under Top Bars,你将发现在Interface Builder中切换Translucent(半透明)设置将导致视图上下移动.在iOS 7中将UINavigationBar设置为半透明将导致视图在UINavigationBar的下面向上移动,而由于iOS 6中不支持设置半透明的UINavigationBar,这个设置在iOS 6中没有任何变化;视图始终保持在UINavigationBar下面,你可以留意到在iOS 6中Black Translucent UIBarStyle被标注为不适用(Deprecated),而其他的UIBarStyle可在iOS 6中创建不透明的UINavigationBar.这个原因导致的情况和我们前面章节讨论的关于新的状态栏的问题非常相似,也就是我们提到的在iOS 7中的可用的屏幕空间高于iOS 6中的情况。

绝大部分由于调整UINavigationBar半透明度所导致的问题可以通过我们前面介绍的方法来解决,然而不论怎样,如果有一个或者多个在UINavigationBar下面向上移动的视图,额外的步骤也就是UIScrollView(或者UIScrollView的子类,比方说UITableView)都是必要的. 如果你使用Storyboard来扩建在UINavigationBar下面向上移动的UIScrollView(或者子类),那么内容插图将被自动设置。自动调整的内容插图为了确保内容在UIScrollView内,将在UINavigationBar下面设置初始的偏移量,因而对用户来说会立即可见。不管怎样,如果使用不太直接的方式操作在UINavigationBar下面向上移动的UIScrollView(或者子类),这里不太直接的方法比如说通过XIB创建,之后加载到容器视图(container view),那么你就需要自己去设置内容插图了。

在Interface Builder中也是可以设置内容插图的,但是针对这种情况,我建议在代码中做这个设置,我们有很多的理由这样建议您,首先,我们只想在iOS 7中而非iOS 6中设置插图,而Interface Builder是不可能实现这样的设置的,其次,我们只想在运行iOS 7时设置内容插图,我们可以使用Top Layout Guide(顶部布局向导)来帮助我们设置内容插图(即便你的Storyboard或XIB没有使用自动布局)。 下面是一个示例来告诉如何通过代码完成这个设置,在这里示例中,我使用了一个UITableView而没使用UIScrollView,因为这是更加普遍的情况。 在访问UIViewController的属性topLayoutGuide之前,必须确保你在iOS 7上或者更高的版本。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {      CGFloat topInset = self.tableView.contentInset.top + [self.topLayoutGuide length];      CGFloat leftInset = self.tableView.contentInset.left;      CGFloat bottomInset = self.tableView.contentInset.bottom;      CGFloat rightInset = self.tableView.contentInset.right;         self.tableView.contentInset = UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset);  }

特别的指出,因为每个App都有唯一的构造,让你的App在视觉吸引力以及全部功能都能完美的运行在iOS 6和iOS 7上是一件非常有挑战的工作。对于同时支持iOS 6和iOS 7,处理兼容性的问题,在这里做出预测以及覆盖所有可能的情况,这几乎是不可能做到的事情,因此希望通过这篇文章帮助大家处理一些常见的情况,并且帮助你在正确的方向上以便更好的处理罕见或复杂的状况。