iOS中的Auto Layout和Frame

1 iOS常用的布局方式

iOS中界面有三种布局方式:Frame,Autoresizing Masks和Auto Layout。

一般而言Frame是最随心所欲的,你可以做你任何想要的改变,但是同时也是最繁琐的,一旦布局发生改变你要更改所有的相关视图的Frame。Autoresizing Masks定义了父视图frame变化时子视图的frame如何变化,这简化了视图外部布局变化时内部视图变化的工作量。Auto Layout使用约束来表示视图间的相应关系,不论是外部变化还是内部变化,视图都可以动态相应,大大简化了我们的布局方式。

以上是三种布局方式的主要特点,但也不绝对,比如使用Frame的时候我们也会根据其他视图的left,right去编写布局,这样也有了视图间的相互关系的意味。使用Auto Layout时的leading,trailing很多时候都是一个常量并不符合我们的要求,还要在视图加载或者变化过程中去修改值才能达到动态响应变化的效果。所以使用哪种布局方式好并没有一个定论,而且我也支持在特定的情况下使用有优势的布局方式。这样就造成了对于生命力较长的项目会出现多种方式并存的局面,本文章主要讲对于Frame和Auto Layout混用情况下的一些避坑策略。

2 视图加载过程

要混用Frame和Auto Layout,必须要搞清楚他们的作用时间和有效范围,这和视图的加载过程有很大的关系。我们在controller视图上面用auto layout添加了一个subview,并在各个系统调用声明周期方法中做了打印处理,结果如下:

viewDidLoad   
viewWillAppear 
viewWillLayoutSubviews(1)  
-updateConstraints   
updateViewConstraints
viewWillLayoutSubviews(2)
viewDidLayoutSubviews   
-layoutSubviews   
-drawRect  
viewDidAppear   

其中前面带有“-”符号的表示的是subview视图的打印。对于viewWillLayoutSubviews出现的顺序根据使用的布局方式会有所区别,使用Frame时出现为viewWillLayoutSubviews(1)位置,使用Auto Layout时出现在viewWillLayoutSubviews(2)位置。

Auto Layout的作用范围是从第三个方法-updateConstraints开始直到viewDidLayoutSubviews完成,在这期间系统是通过view上的约束来计算view上的布局。一般我们都是在viewDidLoad里面编写页面布局代码,如果这时对一个视图同时使用了Auto Layout和Frame,我们会发现frame无效,就是因为这时布局是按照约束来计算的。如果视图的frame在布局过程中发生了改变(比如initWithFrame,使用xib都会给予初始值,但实际布局时我们可能想要更改),这时如果想获取视图的准确frame值,在viewWillAppear中是不行的,只能在自动布局生效后获取到,即我们可以再viewDidLayoutSubviews和viewDidAppear中获取frame的准确值。由上述结果也可以得出,系统的布局是优先使用Auto Layout的,但是布局的最终结果却是将约束转化成视图的frame,理解了这一点对于布局方式的选用也很重要。

要想修改布局,必须要在Auto Layout结束之后才会起作用,否则会被系统将我们的布局按照Auto Layout重新刷新。从上面我们可以看到,我们可以在子视图的-layoutSubviews和-drawRect方法里面修改子视图的布局,但是一般视图为了重用不会在自己的类里面将frame写死,这样我们只有通过controller的viewDidLayoutSubviews和viewDidAppear方法修改视图的frame。但是这样也有问题,在viewDidAppear里面修改布局,我们可以看到一个明显的延迟,系统调用次序使然,我们无法去改变。

所以我的建议就是不要对同一个视图同时使用Frame和Auto Layout去控制同一个视图。如果一个视图使用了某种布局方式,那么尽量保持统一中方式改变布局。

3 不同布局方式混用

不是说可以混用吗,怎么又突然说对同一个视图使用一种方式?那我们来定义一下混用方式: 父视图A包含子视图B、C,子视图B包含子视图B1、B2,子视图C包含子视图C1和C2。如图:


对于B和C我们可以使用Frame的方式布局其在父视图A中的位置和大小,但是对于B1和B2,我们可以使用Auto Layout的方式来布局其在父视图B中的尺寸和位置关系。这就是我理解的混用,对于同一层级的视图使用相同的布局方式,对于不同层级的使用可以使用其他布局方式。

那么它的意义是什么呢?不同view的复杂度决定了我们采取哪种方式来对其布局,我们在开发中有可能会遇到某些流式的布局,我们用Auto Layout可以行云流水,但是对于某个视图当中极其复杂的小控件的布局,Auto Layout显然要写不少的一大段,当两者组合时也就是混用的意义所在。

4 使用过程中的坑

(1) 约束变化后视图更新

有的时候我们更改约束后发现视图并没有变化,这是因为约束改变后并没有触发视图重新布局。如果要重新布局,可以使用layoutIfNeeded()立即更新视图布局,使用setNeedsLayout()在下个绘图周期中触发布局更新。这两个方法都会触发layoutSubviews()方法。

(2)不要启用NSAutoresizingMaskLayoutConstraint

苹果iOS6之后推出了Auto Layout技术,但是还想兼容原来的autoresizing,所以它将autoresizing转化为了约束,转化后的约束类型就是NSAutoresizingMaskLayoutConstraint,这就有可能导致系统为我们添加了许多我们无法预料的约束。当我们添加的约束不,但是视图显示在界面上没有任何问题,这是NSAutoresizingMaskLayoutConstraint帮我们自动补齐了约束。在此情况下有可能出现frame不正确。所以我们在混用时不要开启此属性,即设置其为NO。在storyboard上NSAutoresizingMaskLayoutConstraint默认为开启,纯代码默认为关闭。

总结:
(1)使用Auto Layout时NSAutoresizingMaskLayoutConstraint设置为NO,设置完整清晰的约束。
(2)对同一层级视图使用相同布局方式,对非同一层级视图可以使用不同布局方式。对同一视图在同一布局时间段内不要同时使用不同的布局方式。
(3)搞清视图布局、绘制步骤,区分清楚Frame和Auto Layout的有效范围,在合适的时机进行视图布局变化、更新和frame获取。

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

推荐阅读更多精彩内容