WWDC2016-Xcode 8 AutoLayout 新特性
WWDC2016-Xcode 8 AutoLayout 新特性
目录
- Incrementally Adopting Auto Layout
- Design And Runtime Constraints
- NSGridView
- Layout Feedback Loop Debugging
一、Incrementally Adopting Auto Layout
简单说,目前大部分在IB中布局控件时,一般都是将约束一次性约束完整,避免出现约束警告等错误。在Xcode8中,我们可以不一次性添加好所有的约束,可以一步步将约束完善。
为什么会有这样的需求呢?可以先看下背景来源。
例子:当我吧一个view 放置在父view上面时,不加任何约束的情况下,如下图:
开上去比较正常。但是当我把设备旋转90°时,就会发现如下图:
Snip20160731_2.png此时可以看到,这个view的位置保持与原来一样,并且我们没有设置约束,这是怎么做到的呢?其实,在程序编译时,autolayout会自动隐式的给view 加上相关的约束,保证view的大小不会发生变化。这个view的就被加上的相应的约束。但是我们是并不希望view 超出屏幕之外。我们需要让view随着屏幕旋转二自适应位置的变化。
有没有一种不需要要用约束就可以简单的实现,resize布局呢?
我们可以使用autoresizing masks简单布局。这个是在autolayout之前就出现的布局UI的方式。这是一种Springs & Struts的UI。我们可以设定边缘约束(注:这里的约束并不是指的是Autolayout里面的constraints,是autoresizing masks里面的规则
),无论View的长宽如何变化,这些View都会跟随着设置了约束的view一起变化。
那实现原理又是什么呢? 可以看到xocde8是先取出autoresizing masks,然后在runtime
时候将其转换成相应的constraints,最终就会直接显示。
可以给view 设置 translatesAutoresizingMaskIntoConstraints属性即可。
在autolayout之后,我们约束view就更加方便了,勾选autolayout之后,autoresizing masks 默认就不会出现了。
那么在Xcode8中,我们可以对view 进行增量更新约束,即可以先用AutoresizingMask做简单的布局,之后通过约束进行更改。简而概之,Xcode 8 Autolayout ≈ AutoresizingMask + Autolayout 。
在xcode8 storyboard也进行了更新变化。可以明显看到,在用IB布局界面是可以全设备调整布局情况,这对没有那么多设备的开发者来说是极大的福音啊。
通过简单地布局示例,可以看到我们同过不同屏幕,不同尺寸布局一个界面,更加方便。
Snip20160731_4.png这就是Xcode 8 的Incrementally Adopting Auto Layout,Autoresizing masks + Auto Layout Constraint 一起协同工作!
Design and Runtime Constraints
在我们开发中,大部分都会遇到这样一种情况,view的约束需要在回去数据中才能明确,所以在app运行时,我们无法知道全部的约束情况。
目前有三种方法来应对以上问题。
-
1.Placeholder Constraints
在布局一张图片的时候,我们需要预估下突变的宽高比例。假设我们设置为4:3,此时我们给图片加上约束,记住勾选“place order constraint”
,这个约束会在build time的时候被移除。当我们运行时拿到图片之后,可以给他加上适当的约束和宽高比即可。 -
2.Intrinsic Content Size
有时候会自定义一些UIView或者NSView,这些View里面的content是动态的。Interface Builder并不会运行我们的代码,所以不到app运行的时候我们并不知道里面的大小。我们可以给它设置一个内在的content的大小。
`Setting a design time intrinsic content size only affects a view while editing in Interface Builder.The view will not have this intrinsic content size at runtime.`
注意: 上面的说明intrinsic content size仅仅相当于是在布局的时候一个placeholder,在运行时这个size就没有了。所以如果开发过程中真的需要用到这个内在的content的大小,那么我们需要overriding的content size
- 3.Turn Off Ambiguity Per View
这个是Xcode 8的一个新特性。当上述2种方法都无法解决我们的需求的时候。这个时候就需要用到这种方法了。Xcode 8给了我们可以在constraints产生歧义的时候,可以动态调整警告级别的能力。
在这个场景中,我们仅仅只知道我们需要把这个imageView放在水平位置的中央,但是imageView的大小和它的水平位置我们并不知道。如果我们仅仅只加上了这一个约束的话,Interface Builder就会报红,因为IB这时候根据我们给的constraints,并不能唯一确定当前的view的位置。
如果我们在之后的运行时,拿到图片的完整信息之后,我们自己知道该如何去加constraints,我们知道该如何去排版保证imageView能唯一确定位置的时候,这时我们可以关掉IB的红色警告。找到“Ambiguous”,这里是警告的级别,我们这里选择“Never Verify”,这时就没有红色的警告和错误提醒了。但是选择这一项的前提是,我们能保证之后运行时我们可以加上足够的constraints保证view的位置信息完整。
以上3种方法就是我们在运行时给view增加constraints的解决办法。
三.NSGridView
这是macOS给我们带来的一个新的layout容器。
有时候我们为了维护constraints的正确性是件比较麻烦的事情,比如即使我们就是一组简单的checkboxes,维护constraints也不容易。这个时候我们会选择用stack view来让我们开发更容易一些。
四.Layout Feedback Loop Debugging
有时候我们设置好了constraint之后,没有报任何错误,但是有些情况当我们运行起来的时候就有一堆constraint冲突在debug窗口里面,严重的还会使app直接崩溃。崩溃的情况就是遇到了layout feedback loop。
遇到这种情况,往往是发生在“过渡期”,开始或者结束的时候。如果说你点击了一个button,button相应了你的点击,但是之后button不弹起,一直保持着被按下的状态。
这些信息确实很难收集,这也是为何苹果要为我们专门开发这样一个工具,方便我们来调试,查找问题的原因。
开启这个工具的开关在“Arguments”选项里面。如下图。
UIViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000 -NSViewLayoutFeedbackLoopDebuggingThreshold 100 // 50...1000 // Logs to com.apple.UIKit:LayoutLoop or com.apple.AppKit:LayoutLoop
我们也可以打全局的异常断点exception break point
。
在调试窗口也可以用LLDB命令po出一些调试信息。
总结
这个Xcode 8 给我们的Autolayout融合了之前Autoresizing masks的用法,使两个合并在一起使用,这样不同场景我们可以有更多的选择,可以更加灵活的处理布局的问题。还允许我们能手动调节constraints警告优先级别。
针对macOS的布局问题,又给我们带来了新的控件NSGridView
最后给我们带来的新的调试Layout Feedback Loop Debugging的工具,能让我们平时调试起来比较头疼的问题,有了工具可以有据可循,迅速定位问题,查找问题。