由于自动布局和大量子视图,非常缓慢地关闭 VC

Posted

技术标签:

【中文标题】由于自动布局和大量子视图,非常缓慢地关闭 VC【英文标题】:Dismiss VC very slow due to autolayout and lots of subviews 【发布时间】:2013-11-19 07:54:34 【问题描述】:

我有一个加载了很多子视图的滚动视图,由于我不会进入的原因,我选择了 cell 重用和 UITableView。它工作得很好,当视图被填充时,除了一点初始主线程延迟之外。但是,每次关闭 VC "on top" (e.g. after presenting a modal overtop) 时,都会出现明显的延迟(2-3 秒)。我通过分析器运行它,堆栈跟踪深入研究了 ios / Autolayout,如附图所示。

代码似乎进入 NSLayoutConstraint("+0x06 calll "-[NSLayoutConstraint _addToEngine:]+0x0b")

我能做些什么来绕过这种明显的重新应用约束吗?

【问题讨论】:

IOS 7? IOS 6 试过吗? IOS 7。看看我是否可以针对 iOS 6 并报告。 iOS 6 上也存在问题。 我也看到了同样的情况,您找到解决方案了吗?我正在使用 reloadRowsAtIndexPaths: 和 begin/endUpdates。将其更改为 reloadData 可以修复它。 尚无解决方案。只使用 reloadData,所以没有这样的运气。 【参考方案1】:

为什么你的滚动视图的性能很差

通过查看您的跟踪,您的问题的根源开始于转换回来:您将 80% 以上的时间花在 -[UITransitionView transition:fromView:toView:removeFromView:] 上。此方法会立即将您转换到的视图添加回视图层次结构(随后的 -addSubview: 调用),这需要完整的自动布局传递。

我不知道有什么方法可以强制普通的 iOS 视图控制器转换系统将旧视图保留在后台,可以这么说,以避免这种自动布局传递。 (如果多个视图在屏幕外堆积并开始导致内存压力,这种方法实际上可能会遇到其自身的一系列问题。)

加快现有结构中的自动布局

尽管如此,您可以尝试通过多种方式优化您的自动布局过程。首先,重新设计滚动视图以减少子视图。 Apple 的开发人员技术支持有时也建议扁平化您的视图层次结构;使自动布局减少递归有时会有所帮助。 (例如,参见Florian Kugler 和Martin Pilkington 执行的性能测试。)

您还应始终确保将约束安装在层次结构中可能最深的视图上,同时仍位于与之相关的两个视图的共同祖先上。例如,如果视图 A 具有子视图 B 和 C,您将希望约束仅引用安装在视图 C 上的视图 C,而不是视图 A;但是,A 上需要存在与 B 和 C 相关的约束。这是 all 自动布局工作的一个很好的指导方针,而不仅仅是在这种特殊情况下;在层次结构中安装的约束越深,底层求解器在任何特定级别上的工作速度就越快。

改变你的方法

UITableView 能够通过在自动布局系统中提供一种中断来避免这个问题:表格视图可以通过约束正确定位,然后使用它自己的委托方法(例如-tableView:heightForRowAtIndexPath:)和一些内部布局魔法为每个单元格单独运行自动布局,而不需要一次布局整个视图。常规的 UIScrollViews 没有这种优化的奢侈。

我知道你说过你有理由不在这里采用 UITableView,但你可能会考虑重新审视这些理由。通过切换到 UITableView 并实现委托方法 -tableView:estimatedHeightForRowAtIndexPath:,您可以看到一些非常显着的速度改进,它可以让您在视图加载时短路许多自动布局计算并将它们推迟到您即将滚动的点屏幕上的新单元格。 here on *** 和社区中的其他人都朝着这个方向进行了一些相当重要的实验。 (快速搜索“UITableView Auto Layout height”会出现几十个结果。)

祝你好运!

【讨论】:

感谢您的建议。你已经说服我不会有一个简单的解决方案——我会考虑采用上面的一些建议和最坏的情况,尝试切换回 UITableView (UITableView 黑魔法导致我在应用程序的其他领域出现问题,但是在这种情况下会救我) 这是一个很好的答案。我唯一要补充的是:根据您的实际代码/视图设置的样子,您可能能够使用屏幕外视图层次结构进行一次自动布局计算,然后缓存所有计算出的帧完成一次布局传递后的视图。然后,对于您在屏幕上显示的真实视图层次结构,您可以根据每个视图对应的屏幕外自动布局副本手动设置框架(没有自动布局或任何约束)。显然这需要重新设计,但它肯定会解决您的主要问题。

以上是关于由于自动布局和大量子视图,非常缓慢地关闭 VC的主要内容,如果未能解决你的问题,请参考以下文章

滚动视图不在自动布局中滚动子视图

Xcode 自动布局和旋转

由于自动布局没有计算尺寸,将子视图添加到自定义视图最终会出错

以编程方式使用自动布局实现带有子视图的 uiview 子类

如何使用自动调整大小和自动布局并更改其默认行为? [关闭]

UITableViewCell 子视图不遵守自动布局约束