03 | Auto Layout 是怎么进行自动布局的,性能如何?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
iOS 12的Auto Layout性能得到了显著提升,使其与手写布局几乎具有相同的高性能。Auto Layout是苹果公司提供的基于约束布局的库,通过Cassowary算法实现动态计算视图大小和位置。iOS 12更多地利用Cassowary算法的界面更新策略,解决了Auto Layout性能问题,使开发者可以放心地使用自动布局。此外,文章还提到了Auto Layout的生命周期和性能问题,以及如何提高其易用性,为读者提供了全面的了解和使用Auto Layout的指导。苹果公司还提供了VFL语言和UIStackView来简化Auto Layout的写法,提高iOS开发响应式布局的易用性。文章还提到了苹果公司技术支持人员的观点,强调使用苹果公司的技术能持续获得技术升级。总之,iOS 12的Auto Layout性能提升为开发者带来了更好的开发体验,而苹果公司的持续技术升级也是开发者选择使用其技术的重要原因。
《iOS 开发高手课》,新⼈⾸单¥59
全部留言(107)
- 最新
- 精选
- 一剑寒潇置顶使用 Auto Layout 一定要注意多使用 Compression Resistance Priority 和 Hugging Priority,利用优先级的设置,让布局更加灵活,代码更少,更易于维护。 能否举一些详细的代码事例!!!
作者回复: 有的。你可以看我的这个 demo https://github.com/ming1016/ShowAutoLayout
2019-03-16326 - 开发小能手关于 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-17460 - 徐秀滨针对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-16242 - 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-1630 - 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-1616 - 徐大炮autolayout 的布局代码应该写在什么地方,是在view 的layoutsubview 方法里面写,还是在view 加载完成后写,那个更合理呢?
作者回复: 推荐用 Masonry 和 SnapKit
2019-03-18311 - xilieHi,看了你写的“AutoLayout情况如何计算UITableView的变高高度”,问个问题: 有时候cell里面的一些 label 会在不同情况下切换显示和隐藏,这时 label 的上下间距,会出现异常,比如: 竖着排列3个 label: a-b-c,间距都是20,这时 b 隐藏,c 和 a 的间距是20,设计要求是10,这种怎么处理?
作者回复: layoutsubview 里可以得到 frame 然后判断进行hidden处理
2019-03-1835 - geeklyc看了篇文章比较几种不同计算cell高度性能的问题,从好到坏:手动frame+计算高度,AutoLayout+计算高度,AutoLayout+自动计算。铭神,你的建议是?现在三种情况都用了下
作者回复: cell 情况复杂时用手动frame+计算高度,简单的用AutoLayout+自动计算
2019-03-1734 - wlgemini我也写了一个基于Auto layout的swift框架,在这里:https://github.com/wlgemini/Driftwood
作者回复: 棒棒的
2019-03-183 - 轩关于 Autolayout,iOS 12 具体做了哪些优化呢?
作者回复: 参见 WWDC 2018 202 Session
2019-03-272