WWDC之Mysteries of Auto Layout Part 2

本文为WWDC2015的Session 219 "Mysteries of Auto Layout Part2" 视频笔记,其内容主要涉及了约束的生命周期和,Autolayout调试两大内容,学习记录了视频内容重要的知识内容,欢迎一起探讨研究.

资源

内容

The Layout Cycle

layoutCycle.png

为了说明Layout Cycle,苹果工程师给出了这样以上这张图,果然一图胜千言.基于整个App的运行循环过程中,布局界面上的视图前,首先会进行约束进行更新和设置,然后将最终的布局信息延时地传递给视图,让视图获取到相关Frame的信息,进行位置的尺寸的确定,然后回到主运行循环,等待约束再发生变化.

Constraints Change

  • 约束改变后Frame不会马上变化
  • 重写layoutSubviews要十分当心

让约束发生变化的方式主要由以下三种:
1.使用官方极力推荐的NSLayoutConstraint的``activedeactive`两个类方法来激活,或无效指定约束.(抛弃掉add/remove约束的方式吧~原因可见Mysteries of Auto Layout Part1 16:27)
方法代码如下:

    [NSLayoutConstraint activateConstraints:]
    [NSLayoutConstraint deactivateConstraints:]
    // 参数为NSLayoutConstraint对象的数组

2.修改约束等式的常量值,乘数因子或者优先值.接触过Autolayout我们应该都知道给视图设置约束时要满足一个约束等式如下.(就当你知道了,(╯﹏╰)b)

equal.png

Constant或者Multipler变化时,创建的约束等式也相应改变,使得
Layout引擎重写计算布局.
而对于优先值Priority的改变,往往表现在两个视图间同一位置的约束,将根据优先级高的计算布局属性,除此之外还有具有instrinsic Content Size属性的视图间的contentCompressionResistance或者contentHug的竞争.

3.添加或移除视图,视图都没,跟自己相关的约束当然也没有喽.(╮(╯▽╰)╭)

当约束改变后,Layout引擎就会重新计算新的布局,将布局内容的旧值替换成新值,然后调用父视图的setNeedsLayout.
而对于setNeedsLayout的描述,官方文档给出了详细说明.此方法只是对当前约束变化了的视图了标记,只有等到下一个视图更新周期时视图才会真正响应约束的变化而改变Frame.如果想要让视图快速地响应约束的变化,则需要调用layoutIfNeeded.

Deferred Layout Pass

约束发生变化后,就进入了延迟的布局信息传递过程.为什么说延时的呢?回想一下,我们操作约束变化时经常通过设置动画时间来放大对应Frame的延时改变.在这个阶段里,视图更新所在视图层次内的所有约束,然后重新赋值Frame属性.
更新视图的约束,使用setNeedsUpdateConstraints 就表示着该视图的约束需要更新,而具体的更新会在将来某一时刻进行.其调用的时机,苹果工程师给了两个情景:

  • 当某约束在所在位置变化太慢时,使用update期间将更快的更新约束.
  • 当视图约束频繁且多余的变化时,调用后只会执行最后一次的更新变化.

响应视图布局约束变化后,就到了对视图位置布局的最终设置,而这个过程则是视图从上到下遍历视图层次,调用layoutSuviews(iOS)/layout(OSX),设置具体的内部子视图的Frame.而重写该方法时,主讲人多次提醒开发者需要十分注意重写方法时内部的操作.
重写layoutSuviews方法时,其内部的约束是不完整的,具体表现为有的子视图已经完成了布局,而有的子视图正在或者还未进行布局.为了保证方法的正确执行,我们必须调用父类的layoutSuviews,不能在其内部调用setNeedsUpdateConstraints(时机太晚了,已经进入了布局阶段),并且不能随意地更改约束,防止与其他视图层次相关的约束的改变.

Interacting Legacy Layout (处理系统遗留的布局)

  1. 当我们用代码使用Autolayout给视图添加约束时,要时刻留意将translatesAutoresizingMaskIntoConstraints`设为NO,否则添加完约束后就会出现一下约束警告日志.
    interactConstraint.png
    .这是由于系统默认设置了Yes,给视图添加的固定约束而与我们自己后添加的约束产生了冲突,导致不能同时满足约束条件进行布局.(IB里自动将此属性值设置为No).
  2. 如果想要自己设置内部视图的Frame时,重写layoutSuviews,在此方法里设置,切记不要忘记调用父类方法.

Constraint Creation

关于系统自带API进行约束的创建方式一直以来都被我们诟病,设个约束出要那么大坨代码(差评~)...但如果了解使用VFL创建约束的话还是很优雅的,只是实现的约束有所限制.而现在iOS9提供了新的约束创建方式,让开发者可以更加明了,快速地创建约束.

constraintCreate.png

通过查看UIView的头文件,可以看到viewanchor属性都定义在一个名为UIViewLayoutConstraintCreationUIView分类中.

// NSLayoutXAxisAnchor 类型表示在X轴上的约束
leadingAnchor 
trailingAnchor
leftAnchor 
rightAnchor
centerXAnchor

// NSLayoutXAxisAnchor 类型表示在Y轴上的约束
topAnchor
bottomAnchor
centerYAnchor
firstBaselineAnchor
lastBaselineAnchor 

// NSLayoutDimension 类型表示尺寸相关的约束
widthAnchor 
heightAnchor

初次之外,新的NSLayoutAnchor类的文件里提供了一系列进行相关视图进行约束设置的方法,这里就不一一介绍,可以Command + R进行看看.

Constraining Negative Space

这里所提到的关于对多个视图进行等间距或者同时居中的情况下,以前的做法就是创建假的UIView仅仅为提供约束来达成目的,而现在有了UILayoutGuide对象其表示着一个可以使用Autolayout的布局矩形区域,可以通过视图的分类方法addLayoutGuide添加guide,来充当之前仅仅提供约束的假视图,作用于Autolayout.具体的话就举一个实现让三个按钮等间距排列,结合代码和图应该能刚好理解点.

Screen Shot 2015-12-12 at 10.31.31 PM.png

    //UIButton *saveButton;
    //UIButton *cancelButton;
    //UIButton *clearButton;
    
    UILayoutGuide *space1 = [[UILayoutGuide alloc]init];
    [saveButton addLayoutGuide:space1];
    UILayoutGuide *space2 = [[UILayoutGuide alloc]init];
    [cancelButton addLayoutGuide:space2];

    NSLayoutConstraint *spaceConstraint = [space1.widthAnchor constraintEqualToAnchor:space2.widthAnchor];
    NSLayoutConstraint *constraintOne = [saveButton.rightAnchor constraintEqualToAnchor: space1.leftAnchor];
    NSLayoutConstraint *constraintTow = [cancelButton.leftAnchor constraintEqualToAnchor:space1.rightAnchor];
    NSLayoutConstraint *constraintThree = [cancelButton.rightAnchor constraintEqualToAnchor:space2.leftAnchor];
    NSLayoutConstraint *constraintFour = [clearButton.leftAnchor constraintEqualToAnchor:space2.rightAnchor];
    
    [NSLayoutConstraint activateConstraints:@[spaceConstraint, constraintOne, constraintTow, constraintThree, constraintFour]];

Unsatisfiable Constraints

想要了解Unsatisfiable的具体的相关约束以及关联对象,就必须要理解输出的约束警告日志.

understandLog3.png

现在允许给约束或者视图添加约束标识符identifier字符串属性,将会在日志输出中显示,极大让日志内容更加清晰,让开发者快速找到存在问题的约束和视图.

Resolving Ambiguity

出现Ambigous Layout 警告时表示着约束间存在冲突,而造成约束冲突的原因主要有:

  1. 约束太少
  2. 约束的优先级冲突

针对调试解决办法直接上图(...懒了🙈)
resolvingAmbiguity5.png

总结

本视频从约束布局的生命周期到如何Debug布局问题,对Autolayout引擎的工作流程做了充分了说明和Demo演示,也告诉了我们一些在使用Autolayout中值得注意的地方,对工作中使用和处理Autolayout问题有很大的帮助,作为唯一有字幕(当然是英文的😔)的介绍Autolayout的WWDC Session是值得一看.如果还有说明问题,欢迎留言,一起探讨.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容