纵向模式下的 iOS 自动布局性能问题。 [NSIS引擎优化]

Posted

技术标签:

【中文标题】纵向模式下的 iOS 自动布局性能问题。 [NSIS引擎优化]【英文标题】:iOS autolayout performance issue in portrait mode. [NSISEngine optimize] 【发布时间】:2012-10-18 01:16:31 【问题描述】:

我遇到了一个非常奇怪的问题,我想知道是否有人可以在这里帮助我,因为我完全迷路了。

上下文: 我正在开发一个层次结构相对简单的应用程序。只有几个视图控制器,但有很多高分辨率图像。它们以UIScrollView 的形式显示,并带有一些文本等。在纵向模式下对其进行测试时,滚动视图根本没有平滑滚动。似乎帧速率下降到大约 4-5 fps。一开始我以为是因为高清图片。

但后来我把 iPad 调到了横向模式,一切都运行得很顺利。由于我有一个单独的纵向和横向 xib 文件,我认为纵向 xib 中一定有问题。原来,没有。两者都有相同的 VC 类,因此使用相同的代码和两个 xib 几乎相同,除了视图的大小和位置。

为了缩小问题范围,我使用 Instrument 的 TimeProfiler 查看导致问题的原因。事实证明,TimeProfiler 显示了对[NSISEngine optimize] 的一些调用(由NSLayoutConstraint 触发)。 在纵向模式下,通话次数更多,而且通话时间更长。在树的下方,我看到在纵向模式下[NSISEngine optimize] 称为[NSISEngine fixupIntegralizationViolations],而在横向模式下却没有。

我什至从应用程序中删除了所有视图控制器,除了 rootVC 和 rootVC 提供的另一个。呈现的 vc 仅包含一些图像、按钮和一些动画。它只有一个 xib 用于两个方向,并且(与所有其他方向一样)使用自动布局进行布局。

布局在两个方向上都可以正常工作,并且没有歧义(据我所知。至少po [[UIWindow keyWindow] _autolayoutTrace] 没有显示任何内容)。

我附上了vc演示过程的TimeProfile截图。一张是纵向的,一张是横向的。如您所见,在横向调用[NSISEngine optimize] 只需一毫秒,而纵向调用则需要 3000 毫秒以上。

有谁能告诉我这是为什么?或者也许知道我能做些什么来找出问题所在?

任何帮助将不胜感激!

谢谢

图片大图链接:link

【问题讨论】:

【参考方案1】:

我在中等复杂的视图中遇到了同样的问题,它在非 Retina iPad 或纵向模式下的 Retina iPad 上表现良好。在 Retina 设备的横向模式下,显示弹出框或在视图堆栈上推送另一个视图需要 10 倍的时间。我最终在视图控制器中用手动编码的 loadView 替换了 XIB 文件。这似乎已经消除了这个问题。界面生成器倾向于创建过多的约束,因此控制它是良好的自动布局性能的关键。

我也为此问题开过一张支持票。

更新:

我在我的情况中找到了原因。它是以下一组约束:

NSArray *constraints = [NSLayoutConstraint
                        constraintsWithVisualFormat : @"|[sunLabel][monLabel(==sunLabel)][tueLabel(==sunLabel)][wedLabel(==sunLabel)][thuLabel(==sunLabel)][friLabel(==sunLabel)][satLabel(==sunLabel)]|"
                        options : 0
                        metrics : nil
                        views : labelViewsDictionary];

它指定一个父视图中的 7 个标签都共享相同的大小,并且都扩展了父视图的宽度。我相信布局的过度关系性质使自动布局适合,特别是因为父视图宽度不能被 7 整除。

为了解决这个问题,我创建了一组约束来指定每个标签的宽度并应用这些约束。当设备旋转父视图宽度时,我会返回并将约束上的常量调整为父视图宽度的 1/7。这现在表现良好,加载弹出框的过程现在需要不到 300 毫秒而不是 2000 毫秒。

【讨论】:

【参考方案2】:

我就这个问题提交了技术支持请求,最后得到了答案,这很可能是一个错误。已提交错误报告。希望他们能尽快修复它。如果有任何消息我会更新这个答案。

【讨论】:

只是好奇您是否对此错误报告有任何跟进?我一直在奇怪的自动布局延迟方面遇到类似的问题,仪器显示许多对 NSISEngine fixUpIntegralizationViolations 的调用...... 不,遗憾的是我还没有听到任何消息【参考方案3】:

我昨天在 Ipad ios6.1 设备上遇到了同样的问题。检测应用程序发现,每次调用方法 fixupIntegralizationViolations 大约需要 300 毫秒(大约 20 次,这很多),这使得应用程序完全无用。

我的问题与 Jack Cox cmets 非常相似,但我以不同的方式解决了它。我的限制是:

@"H:|[allButton][inStoreButton(==allButton)][onlineButton(==allButton)][sortButton(50)]|"

问题是这里的 parentView 是整个 iPad 横向宽度,所以这个约束的数学是给每个按钮这个宽度:(1024-50)/3 = 324.6666667。

这在自动布局中通常不是问题,因为它会处理大浮点数并正确舍入它们,但似乎在 iPad iOS6 Landscape 中舍入此数字会触发阻塞 UI 的错误。为了解决这个问题,我所要做的就是将 sortButton 更改为 52,因此现在每个按钮的宽度为:(1024-52)/3 = 324。仅此而已。现在方法 fixupIntegralizationViolations 每次调用大约需要 1ms。

有趣的是,使用 52 在横向中给出了非十进制宽度,但在纵向中确实给出了十进制数:(768-52)/3 = 238.666667。但是,纵向似乎没有任何错误,并且自动布局正确地将数字四舍五入。

【讨论】:

以上是关于纵向模式下的 iOS 自动布局性能问题。 [NSIS引擎优化]的主要内容,如果未能解决你的问题,请参考以下文章

纵向模式下的动画UIView在ios上横向不一致

由于纵向尺寸的超视帧,iOS自动布局在横向模式下不正确?

只有一种布局设计,适合 iPhone 纵向模式下的所有屏幕尺寸

相同的自动布局约束在纵向和横向中表现不同

iOS - 自动布局 - 在方向更改时按比例增加/减小视图大小

ios7 iPad横向模式下的错误视图大小