3

I am creating a popup menu. It has a UIPresentationController that calculates frameOfPresentedViewInContainerView based on presented view controller's view size before showing it.

  • Presented view controllers consist of the fixed height outer (navigation) view controller embedding some dynamic height inner (content) view controller;
  • Inner view controllers, under the hood, have UIStackView wrapped in a UIScrollView;
  • Before calculating size of inner view controller I am calling layoutIfNeeded() on it.

The problem occurred only on devices with the notch (I blame safeAreaLayout) and only with a UIStackView-based inner view controllers. When layoutIfNeeded() called on presented controller (e.x. when display orientation change, content size change, or presented second time) UIKitCore goes into an infinite loop calling -[UIView layoutGuides]. It doesn't crash the app, but use 100% of the main thread and freezes the UI(sometimes whole phone to the point you need make a hard reset), consuming about 10Mb of memory every second.

I was able to fix it by adding 1 extra point to a calculated height of the frameOfPresentedViewInContainerView. This sounds like an awful fix, so I am trying to better understand the problem.

I would be glad if someone with a deep understanding of UIKit could point me to a better strategy on how to debug/investigate the issue.


UPDATE

Seems like UIScrollView having hard time positioning content due to a safeArea. UIKitCore keeps repeating those 5 lines:

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

I also have

runtime: Layout Issues: Scrollable content size is ambiguous for UIScrollView.
Vladimir
  • 345
  • 1
  • 13
  • I'm not sure if that was the case with your code, but I found a similar problem when I had a view added to the scroll view that was from a child view controller of the one hosting the scroll view, and the issue happened because I forgot to add the child view controller (addChild() and then didMove(...)) – vfn Oct 12 '20 at 06:28
  • What do you mean by "UIKitCore". There is NO framework component in apple named "UIKitCore". You must mean UIKit. – user3335999 Feb 15 '21 at 05:11

1 Answers1

2

I was able to fix my issue by specifically attaching UIScrollView to the bottom of safeAreaLayoutGuide.

var bottomConstraint = formView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
if #available(iOS 11.0, *) {
    bottomConstraint = formView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
}
Vladimir
  • 345
  • 1
  • 13