iOS发展到如今,iOS5的占有率已经很低了(估计多数还在使用iOS5系统的用户活跃度也不高吧),所以兼容最低版本iOS6.0也不会损失太多用户。同时,下一代大屏iPhone已经发售了,Autolayout绝对是其中一个重要的界面兼容手段。为了能尽快作好适配好新设备的工做,我相信学习Autolayout这门技术也是必不可少。我做为一个使用了Autolayout大约一周左右的初学者,就在这里记录一下一些要点吧。git
1、Autolayout的简要背景
Autolayout这个东西是从iOS6开始才出现的,在没有Autolayout的远古年代,你们是用Autoresizing作一些简单的界面拉伸的。
这里先说一下Autoresizing,这个东西支持width和height的四方向拉伸,也能够对x和y作一些简单的四方向对齐。固然,Autoresizing仍是基于绝对坐标的,因此界面上的元素仍是须要设置好对应的坐标。支持ib和代码设置,以下图
github
1self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
能够看到代码其实就是设置UIViewAutoresizing枚举变量,代码也是比较简单的。利用Autoresizing就已经能很好适配了搭载iOS6的iPhone5(有部分界面仍是须要多个containerview或者写代码手动调节的,不过并不复杂),那为什么Apple还要画蛇添足推出Autolayout呢?
从实用性来看,应对iPhone5之流,Autoresizing足矣,且有兼容性的优点。可是如今时代变了,Android满地开花的大屏手机(5吋以上才能称做大屏),Apple为了保持自有优点,我认为大屏设备和界面的大一统将会是将来战略(iPhone可使用原来iPad的专用控件)。这必然致使界面的适配问题,最起码Autoresizing已经显得无力了,同时对于部分须要有横向界面的应用会有更复杂的调整工做。若是不使用Autolayout,改用代码手工适配的话,工做量也不算少,同时会须要大量的魔术数来定位坐标。这彻底不是现代界面该有的开发方式,实在太原始了。随着iOS8的到来,Autoresizing的兼容性优点会逐渐消失,事实上要同时兼容4个大版本的iOS,这难度的确不小。
所以,如今开始学习并使用Autolayout是一个不错的时机。除了上述因素,从开发工具来看,对于Autolayout的支持已经比Xcode5以前好了很多。其次,针对Autolayout的开源工具库也已经相对成熟,前人踩过的坑大多均可以找到对应解决方法。因此,我实在想不出一个拒绝Autolayout的理由。ide
2、Autolayout的基础知识
若是你们对Android有所了解,应该知道他们是经过dp的相对坐标和一些布局来定位控件的(好吧,可能我用词不太正确)。但iOS的Autolayout思路和Android的布局思路,仍是有很大的差别。Autolayout的本质是约束,经过设定足够多的约束条件,来得出每个控件的最终坐标。约束条件之间不能相互矛盾,不然会出错抛出异常。条件之间的矛盾仍是比较难描述的,这个我在下面的内容再举例说明。
约束的条件有几种类别:
一、大小(Width、Height、WidthEqually等)
二、间隔(HorizontalSpacing等)
三、对齐(TopEdges、HorizontalCenters等)
在使用Autolayout的界面里,若是控件不添加任何约束的话,仍是可使用绝对坐标定位的。可是,Autoresizing和Autolayout在同一个界面层级是不能共存的,只能选择其一。不过实际操做上,Autolayout要实现某些Autoresizing的功能是彻底能够的,可是步骤不必定比之前简单。
对于一个控件来讲,从前的定位是经过设置frame的4个变量来控制的。但在Autolayout的世界里,这些绝对的数值已经不那么重要了。Autolayout在运行时计算出这些数值也是须要最少2个约束,大多数状况还须要4个以上。
2个约束的例子:
系统的UIActivityView是固定大小的,因此只须要添加x和y的约束。
3个约束的例子:
UILabel类控件,其长度能够由系统计算文字数量和大小得出,因此width或者height的约束能够省去一个。其他两个约束就是x和y的约束,具体表现为HorizontalSpacing等。
4个约束的例子实际上就是多了上述例子一个width或者height约束。
从这些例子,能够得出一个结论,对于一个控件而言,x和y是不可能避免的约束,因此使用Autolayout的控件最少须要2个约束。固然,大多数状况是4个约束起步,同时还须要控件间的各类约束来构建一个完整的界面。
同时在Autolayout的光环下,基本再也不须要手动设置frame。使用Autolayout的控件,frame只是表示这个控件当前的坐标。只有相关的约束有变化或约束的控件发生变化,随之这frame也会变化。这些在InterfaceBuilder中能够很容易体现出来,你能够当即看到控件在任意状况下的变化。
3、Autolayout实践应用
这里的实践以ib为主,我在这里解释一下,设置Autolayout实际上有3种方法,分别是:ib、可视语言和传统代码。我分别说说这些方法的特色:
一、ib
直观简单,所见即所得,实时控制界面变化。系统还会提醒冲突和缺乏约束,并给出修改建议(建议一般不是最好)。对于约束相对静态的界面,开发效率高。但在复杂页面中,经常是100+的约束,不是很友好。同时,对界面内的控件复用比较麻烦,形成大量相相似约束。某些控件不能直接往其添加子控件,如UILabel添加一个UIImageView到其中。
二、可视语言
须要编写代码,同时要求对Autolayout的体系比较熟悉。因为其语言样式能够比较容易看出控件间的约束关系,因此仍是比传统代码直观,但仍是没法预想运行时的变化。一次能够添加多个约束,并在运行时改变约束,可是不能完整实现全部约束功能。同时可视语言也有一些学习成本,没有对应的代码建议,因此须要额外的检查来保证语法正确。
三、传统代码
其实就是调用普通的API,参数比较多,可是能够实现Autolayout的全部功能。从代码量来看,要比可视语言多。这种方法更偏向于相似传统code界面,对于一个100+约束的界面,我想仍是挺吃力的。不过,在复用性方面有必定的优点,和可视语言同样,能够在运行时改变约束。此外,使用PureLayout开源库能够在必定程度上简化代码。
做为新手而言,经过ib来学习Autolayout是最友好的,能够很直观地观察界面的变化。刚开始时,最容易出现的问题就是遗漏了添加一些必要约束,形成指望与实际不符。ib能检查出约束是否完整,并给予建议,让新手迅速适应Autolayout的开发。工具
ib会提示警告和错误,警告通常不会在运行时产生异常,但错误是务必要解决的,由于运行时是必定会有异常的。布局
出现警告的缘由通常是frame没有更新,这个能够直接update一下。性能
而出现错误的缘由则是缺乏必要约束或者是约束冲突。前者的解决方法是补全约束,后者的状况有点复杂。所谓的约束冲突就是没有办法同时知足全部约束,从而产生冲突。通常是经过删除一些约束,使全部约束均可以知足,我的不建议经过修改约束的优先级来解决。如非特殊状况,通常都是添加越少约束越好,这样思路越清晰,同时对于运行效率都有必定帮助。从目前经验来看,通常的界面开发,的确是用不到优先级的(楼主目前的经验)。
能够看到这些建议不是惟一的,是选择其中一个来补全约束的。新手能够选择系统的建议,看看补充了什么约束,但长远来讲,不建议直接使用系统建议补充的约束。我的认为ib的这些警告和错误对于开发界面来讲,是极其高效的,但建议却不是很是智能。特别是补充约束的建议,一般和你心中指望的界面是差距很大的。
对于单个控件,能够直接经过菜单或者右下角来添加约束,学习
右下角的按钮还能一下添加多个约束开发工具
对于控件间的约束则须要按住Command+点击,选中多个控件再添加约束。测试
约束其实也是对象,所以会出如今坐标的列表优化
同时,约束也支持outlet
约束为何也须要outlet?显然是为了调用某些方法,而下降了遍历约束难度。
在ib上拉几个控件,就能够完成了上面的简单实践了。可是,光这些是不足以完成适配不一样屏幕的开发。
4、Autolayout的复杂约束
Autolayout中的UILabel类控件大小是自适应的,所以通常不须要指定width和height。并且,固定width和height的这类约束要尽可能少用(UIImageView这类仍是不反对使用),这类约束通常会限制你的思惟。如何多个UILabel并排在同一行,可是行宽有限,同时每一个UILabel都有较多的字数。那么应该如何控制某个UILabel能够优先完整显示?这时就要利用抗拉伸和抗压缩的优先级了
还有一个相对特别的属性是比例,支持输入相似“16:9”这类有无穷小数的值。具体应用以下,
这个约束可使控件跟随父视图的大小按比例变化,有相似于以前Autoresizing的效果。
既然约束也是对象,运行动态改变约束的值,则能够达到更多复杂的控制。为了操做方便,咱们能够为一些约束建立outlet。同时在运行时,根据须要动态改变约束的数值或者移除添加约束等,这时,为了操做方便,我使用了一个开源库PureLayout。利用PureLayout就能够很方便地,对约束进行操做,其API要比系统的友好很多。github地址:https://github.com/smileyborg/PureLayout。
暂时发现的坑:一、在tableView的tableHeaderView使用Autolayout时务必要注意,不要使用严格的约束来限制了整个view的大小,不然运行时十有八九会出错。还有,改变tableView大小时,也有一些错位的状况,暂时无解。tableFooterView的状况未测试,估计应该同样。二、在iOS6上约束的容错性更差,更容易报异常,例若有两个相同约束,iOS6上会有异常断点,但不会崩溃;iOS7上无任何异常出错。固然存在多个相同约束是不规范的行为,编写约束时应尽可能作到用最少的约束去达到最佳的效果。三、Autolayout也是有性能问题的,目前我在iOS6的iPod Touch4上测试100个左右约束的界面。在刷新tableView和添加视图等操做时,能明显感受到延迟。通过一系列操做,甚至会出现1分钟以上的延迟,这时没法接受的。能够得出一个结论,Autolayout在约束较多的时候,在低端机器上也是会形成性能瓶颈的。不过,幸运的是,我在iOS7上的4s运行一样的界面,就几乎没有延迟。随着低端设备被淘汰,这个问题会获得缓解的。最后的一个建议是,不要过早地使用Autolayout优化,由于实际上有些界面使用Autoresizing也是能很好地完成适配工做的。同时,对于tableView这类控件使用Autolayout,须要多加留心。