1

我正在创建一个弹出菜单。它有一个在显示之前根据呈现的视图控制器的视图大小进行UIPresentationController计算。frameOfPresentedViewInContainerView

  • 呈现的视图控制器由固定高度的外部(导航)视图控制器嵌入一些动态高度的内部(内容)视图控制器组成;
  • 内部视图控制器,在引擎盖下,UIStackView包裹在UIScrollView;
  • 在计算内部视图控制器的大小之前,我正在调用layoutIfNeeded()它。

该问题仅发生在带有缺口的设备上(我责怪 safeAreaLayout),并且仅发生在基于 UIStackView 的内部视图控制器上。当layoutIfNeeded()在呈现的控制器上调用时(例如,当显示方向改变、内容大小改变或第二次呈现时)UIKitCore 进入无限循环调用-[UIView layoutGuides]。它不会使应用程序崩溃,而是使用 100% 的主线程并冻结 UI(有时整个手机都需要硬重置),每秒消耗大约 10Mb 的内存。

我能够通过frameOfPresentedViewInContainerView. 这听起来像是一个糟糕的修复,所以我试图更好地理解这个问题。

如果对 UIKit 有深入了解的人可以为我指出如何调试/调查问题的更好策略,我会很高兴。


更新

由于安全区域,似乎UIScrollView很难定位内容。UIKitCore 不断重复这 5 行:

- [UIScrollView _layoutGuideOfType:createIfNecessary:]
- [NSISEngine(_UILayoutEngineStatistics)_UIKitPerformPendingChangeNotifications]
- [UIView layoutGuides]
- [_UIScrollViewScrollIndicator _layoutFillViewAnimated:]
- [UIView(AdditionalLayoutSupport) nsli_lowerAttribute:intoExpression:withCoefficient:forConstraint:onBehalfOfLayoutGuide:]

我也有

runtime: Layout Issues: Scrollable content size is ambiguous for UIScrollView.
4

1 回答 1

0

我能够通过专门将 UIScrollView 附加到 safeAreaLayoutGuide 的底部来解决我的问题。

var bottomConstraint = formView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
if #available(iOS 11.0, *) {
    bottomConstraint = formView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
}
于 2020-02-11T12:26:34.080 回答