iOS开发高手课
戴铭
前滴滴出行技术专家
立即订阅
11464 人已学习
课程目录
已完结 46 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 锚定一个点,然后在这个点上深耕
免费
基础篇 (20讲)
01 | 建立你自己的iOS开发知识体系
02 | App 启动速度怎么做优化与监控?
03 | Auto Layout 是怎么进行自动布局的,性能如何?
04 | 项目大了人员多了,架构怎么设计更合理?
05 | 链接器:符号是怎么绑定到地址上的?
06 | App 如何通过注入动态库的方式实现极速编译调试?
07 | Clang、Infer 和 OCLint ,我们应该使用谁来做静态分析?
08 | 如何利用 Clang 为 App 提质?
09 | 无侵入的埋点方案如何实现?
10 | 包大小:如何从资源和代码层面实现全方位瘦身?
11 | 热点问题答疑(一):基础模块问题答疑
12 | iOS 崩溃千奇百怪,如何全面监控?
13 | 如何利用 RunLoop 原理去监控卡顿?
14 | 临近 OOM,如何获取详细内存分配信息,分析内存问题?
15 | 日志监控:怎样获取 App 中的全量日志?
16 | 性能监控:衡量 App 质量的那把尺
17 | 远超你想象的多线程的那些坑
18 | 怎么减少 App 电量消耗?
19 | 热点问题答疑(二):基础模块问题答疑
20 | iOS开发的最佳学习路径是什么?
应用开发篇 (12讲)
21 | 除了 Cocoa,iOS还可以用哪些 GUI 框架开发?
22 | 细说 iOS 响应式框架变迁,哪些思想可以为我所用?
23 | 如何构造酷炫的物理效果和过场动画效果?
24 | A/B 测试:验证决策效果的利器
25 | 怎样构建底层的发布和订阅事件总线?
26 | 如何提高 JSON 解析的性能?
27 | 如何用 Flexbox 思路开发?跟自动布局比,Flexbox 好在哪?
28 | 怎么应对各种富文本表现需求?
29 | 如何在 iOS 中进行面向测试驱动开发和面向行为驱动开发?
30 | 如何制定一套适合自己团队的 iOS 编码规范?
31 | iOS 开发学习资料和书单推荐
32 | 热点问题答疑(三)
原理篇 (6讲)
33 | iOS 系统内核 XNU:App 如何加载?
34 | iOS 黑魔法 Runtime Method Swizzling 背后的原理
35 | libffi:动态调用和定义 C 函数
36 | iOS 是怎么管理内存的?
37 | 如何编写 Clang 插件?
38 | 热点问题答疑(四)
原生与前端共舞 (5讲)
39 | 打通前端与原生的桥梁:JavaScriptCore 能干哪些事情?
40 | React Native、Flutter 等,这些跨端方案怎么选?
41 | 原生布局转到前端布局,开发思路有哪些转变?
42 | iOS原生、大前端和Flutter分别是怎么渲染的?
43 | 剖析使 App 具有动态化和热更新能力的方案
用户故事 (1讲)
用户故事 | 我是如何学习这个专栏的?
结束语 (1讲)
结束语 | 慢几步,深几度
iOS开发高手课
登录|注册

03 | Auto Layout 是怎么进行自动布局的,性能如何?

戴铭 2019-03-16
你好,我是戴铭。今天我来跟你聊下 Auto Layout 。
Auto Layout ,是苹果公司提供的一个基于约束布局,动态计算视图大小和位置的库,并且已经集成到了 Xcode 开发环境里。
在引入 Auto Layout 这种自动布局方式之前,iOS 开发都是采用手动布局的方式。而手动布局的方式,原始落后、界面开发维护效率低,对从事过前端开发的人来说更是难以适应。所以,苹果需要提供更好的界面引擎来提升开发者的体验,Auto Layout 随之出现。
苹果公司早在 iOS 6 系统时就引入了 Auto Layout,但是直到现在还有很多开发者迟迟不愿使用 它,其原因就在于对其性能的担忧。即使后来,苹果公司推出了在 Auto Layout 基础上模仿前端 Flexbox 布局思路的 UIStackView 工具,提高了开发体验和效率,也无法解除开发者们对其性能的顾虑。
那么,Auto Layout 到底是如何实现自动布局的,这种布局算法真的会影响性能吗?
另外,苹果公司在 WWDC 2018 的“ WWDC 220 Session High Performance Auto Layout”Session 中介绍说: iOS 12 将大幅提高 Auto Layout 性能,使滑动达到满帧,这又是如何做到的呢?你是应该选择继续手动布局还是选择 Auto Layout 呢?
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《iOS开发高手课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(96)

  • 长腿欧巴 置顶
    使用 Auto Layout 一定要注意多使用 Compression Resistance Priority 和 Hugging Priority,利用优先级的设置,让布局更加灵活,代码更少,更易于维护。

    能否举一些详细的代码事例!!!

    作者回复: 有的。你可以看我的这个 demo https://github.com/ming1016/ShowAutoLayout

    2019-03-16
    1
    18
  • 开发小能手
    关于 UI 的布局,是使用 frame 还是 Auto Layout ?这个问题困扰了我很久,在之前的团队中是建议使用 frame 的,原因是在 layoutSubviews 中做布局,将所有的子视图按照 UI 显示从上至下、从左至右的顺序来布局,感觉也很规范,代码也不会导致不易维护的程度。
    我一直有这么一条原则:简单的 UI 使用 Auto Layout ,复杂的 UI 使用 frame。原因如下:
    1、从代码量上来看,两种布局方式相差不大。有时候发现复杂的 UI 使用 Auto Layout 的话,代码量反而会变多,因为复杂的 UI 往往会有复杂的逻辑,比如根据数据的不同,部分 UI 的显示会有变动(比如某个子视图隐藏与显示, 会影响到其它视图的布局)。
    2、会将那种仅做了一次约束之后,就可以不用做太多 update 的那种视为简单的布局,这种情况下使用 Auto Layout 还是挺方便的。
    3、会将 Cell 的高度会随着数据的不同而不同的布局视为复杂的 UI 布局,这种情况下使用 Auto Layout 来布局,感觉就不合适。因为不管是 frame 还是 Auto Layout,都需要去计算高度,其实在计算 高度的时候,所有的子视图的 frame 都已经决定了,这种情况下,直接使用 frame 会比较精简。
    4、我见过这样的代码:动态的通过文本,计算出尺寸之后,再使用 Auto Layout 进行 update,感觉太没有这个必要了。

    以上是我对 UI 布局的一点思考,请教大神:凭您的经验,这样的思考有什么不合理之处么?(简单的 UI 使用 Auto Layout ,复杂的 UI 使用 frame。)

    作者回复: 这样想没有问题

    2019-03-17
    1
    35
  • 徐秀滨
    针对Auto Layout的生命周期,我是这么理解的:
    Auto Layout拥有一套Layout Engine引擎,由它来主导页面的布局。App启动后,主线程的Run Loop会一直处于监听状态,当约束发生变化后会触发Deffered Layout Pass(延迟布局传递),在里面做容错处理(约束丢失等情况)并把view标识为dirty状态,然后Run Loop再次进入监听阶段。当下一次刷新屏幕动作来临(或者是调用layoutIfNeeded)时,Layout Engine 会从上到下调用 layoutSubviews() ,通过 Cassowary算法计算各个子视图的位置,算出来后将子视图的frame从Layout Engine拷贝出来,接下来的过程就跟手写frame是一样的了。
    这样可对?

    作者回复: 对

    2019-03-16
    25
  • burning😕🙄
    没有讲到 cell 里面 label的高度自适应问题,这个在layout应该使用频率比较高吧

    作者回复: 具体使用,可以看我这篇文章,里面涉及到
    https://github.com/ming1016/study/wiki/Masonry

    我把相关内容截取到这里

    主要是UILabel的高度会有变化,所以这里主要是说说label变化时如何处理,设置UILabel的时候注意要设置preferredMaxLayoutWidth这个宽度,还有ContentHuggingPriority为UILayoutPriorityRequried

    CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 10 * 2;

    textLabel = [UILabel new];
    textLabel.numberOfLines = 0;
    textLabel.preferredMaxLayoutWidth = maxWidth;
    [self.contentView addSubview:textLabel];

    [textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(statusView.mas_bottom).with.offset(10);
        make.left.equalTo(self.contentView).with.offset(10);
        make.right.equalTo(self.contentView).with.offset(-10);
        make.bottom.equalTo(self.contentView).with.offset(-10);
    }];

    [_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

    如果版本支持最低版本为iOS 8以上的话可以直接利用UITableViewAutomaticDimension在tableview的heightForRowAtIndexPath直接返回即可。

    tableView.rowHeight = UITableViewAutomaticDimension;
    tableView.estimatedRowHeight = 80; //减少第一次计算量,iOS7后支持

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        // 只用返回这个!
        return UITableViewAutomaticDimension;
    }

    但如果需要兼容iOS 8之前版本的话,就要回到老路子上了,主要是用systemLayoutSizeFittingSize来取高。步骤是先在数据model中添加一个height的属性用来缓存高,然后在table view的heightForRowAtIndexPath代理里static一个只初始化一次的Cell实例,然后根据model内容填充数据,最后根据cell的contentView的systemLayoutSizeFittingSize的方法获取到cell的高。具体代码如下

    //在model中添加属性缓存高度
    @interface DataModel : NSObject
    @property (copy, nonatomic) NSString *text;
    @property (assign, nonatomic) CGFloat cellHeight; //缓存高度
    @end

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        static CustomCell *cell;
        //只初始化一次cell
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])];
      

    还有这篇 https://ming1016.github.io/2015/11/03/deeply-analyse-autolayout/ 会讲的更详细些

    2019-03-16
    17
  • power
    不知道大家对视图依赖的处理有没有很好的方法:A依赖B,B依赖C,C依赖D,BC有可能不存在,所以D的依赖有可能是ABC,这种有没有好的布局思路呢
    2019-03-18
    1
    11
  • Hello灬麦德姆
    有一会面试面试官问我AutoLayout怎么实现的,我懵逼了,相见恨晚啊!
    2019-03-16
    10
  • Sean Ma
    我想了解下自动布局会在哪一个时机下能够拿到相应的frame和center,因为有时候做完约束,我想在viewdidlayer前拿到其frame。另外自动布局怎么做动画

    作者回复: 文章有提到。Layout Engine 会从上到下调用 layoutSu... 这个部份。

    动画的话。因为布局约束就是要脱离frame这种表达方式的,可是动画是需要根据这个来执行,这里面就会有些矛盾,不过根据前面说到的布局约束的原理,在某个时刻约束也是会被还原成frame使视图显示,这个时刻可以通过layoutIfNeeded这个方法来进行控制。具体代码如下

    [aniView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.left.right.equalTo(self.view).offset(10);
    }];

    [aniView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view).offset(30);
    }];

    [UIView animateWithDuration:3 animations:^{
        [self.view layoutIfNeeded];
    }];

    2019-03-16
    10
  • 徐扬
    autolayout 的布局代码应该写在什么地方,是在view 的layoutsubview 方法里面写,还是在view 加载完成后写,那个更合理呢?

    作者回复: 推荐用 Masonry 和 SnapKit

    2019-03-18
    1
    9
  • xilie
    Hi,看了你写的“AutoLayout情况如何计算UITableView的变高高度”,问个问题:

    有时候cell里面的一些 label 会在不同情况下切换显示和隐藏,这时 label 的上下间距,会出现异常,比如:
    竖着排列3个 label: a-b-c,间距都是20,这时 b 隐藏,c 和 a 的间距是20,设计要求是10,这种怎么处理?

    作者回复: layoutsubview 里可以得到 frame 然后判断进行hidden处理

    2019-03-18
    1
    5
  • drunkenMouse
    把循环这部分总结了一下:
    触发约束变化 —> Layout Engine就需要重新计算布局,会先获取到当前的布局,调用SuperView.SetNeedLayout() —> Deffered Layout Pass进行监听 —> Layout Engine 从上到下调用LayoutSubViews(),通过Cassowary算法计算各个子视图的位置,算出来后将子视图的Frame从Layout Engine里拷贝出来 —> 和手写布局的绘制、渲染一样。
    2019-03-19
    3
  • 王路广
    我也写了一个基于Auto layout的swift框架,在这里:https://github.com/wlgemini/Driftwood

    作者回复: 棒棒的

    2019-03-18
    3
  • BoomBoom冰Boom
    Flexbox布局iOS开发用的少 一般都是frame或者Masonry
    2019-03-16
    3
  • 关于 Autolayout,iOS 12 具体做了哪些优化呢?

    作者回复: 参见 WWDC 2018 202 Session

    2019-03-27
    2
  • Bo.zhang
    戴神 为什么https://github.com/ming1016/STMAssembleView 下载后程序运行后出link错误 怎么修改呢?
    2019-03-24
    1
    2
  • liyoucheng
    看了篇文章比较几种不同计算cell高度性能的问题,从好到坏:手动frame+计算高度,AutoLayout+计算高度,AutoLayout+自动计算。铭神,你的建议是?现在三种情况都用了下

    作者回复: cell 情况复杂时用手动frame+计算高度,简单的用AutoLayout+自动计算

    2019-03-17
    2
  • 张松超
    不推荐使用xib吗,还是不推荐使用拖线的方式

    作者回复: 简单页面用 xib 没什么问题

    2019-03-17
    2
  • 徐秀滨
    请问,使用xib画页面能够快速提高开发效率,但是怎么在MVC架构上合理使用呢?比如新建一个VC,勾上xib选项后,那么就会创建一个xib文件,这时候xib文件与VC位于同一目录下。
    1. 从文件分类来讲,xib属于View层,VC属于C层,这就不对了。
    2. 而且xib上有响应动作的话该怎么处理才能做到符合MVC分离,且不失了直接拉线写method这种便利性呢?

    作者回复: VC.view 了解下。以外的才是 C 层

    2019-03-16
    2
  • Anyeler
    主要公司的APP支持iOS8.0以上,所以UIStackView比较少用

    作者回复: 孙源的 FDStackView 了解下。 https://github.com/forkingdog/FDStackView

    2019-03-16
    2
  • 断虹残雪
    铭神、请问使用Autolayout,如何适配多套主题(夜间模式)呢?我们现在的做法是每一个xib的view都拉线到代码,然后再代码做主题适配。一直感觉不太好,很繁琐...

    作者回复: 我推荐全代码,可以使用三方库简化写法,或者自己定义 DSL

    2019-03-16
    2
  • 吃蘑菇的大灰狼
    UIStackView的推出从iOS9到现在已经很久了, 他确实更方便布局,但是在平常的开发里面,貌似没看到有很多小伙伴在用, 记得有一篇文章提到,苹果的开发人员建议 ,如果能用UIStackView的,尽量都用UIStackView. 之前不知道原因,读了这篇戴老师的文章才知道UIStackView布局的原理。期待后续的文章。
    2019-03-16
    2
收起评论
96
返回
顶部