Issue #570
Use viewSafeArea
@available(iOS 11.0, *)
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
self.collectionView.reloadData()
}
Use https://developer.apple.com/documentation/uikit/uiview/2891102-safearealayoutguide
view.safeAreaLayoutGuide.layoutFrame
https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets
For the view controller’s root view, the insets account for the status bar, other visible bars, and any additional insets that you specified using the additionalSafeAreaInsets property of your view controller. For other views in the view hierarchy, the insets reflect only the portion of the view that is covered. For example, if a view is entirely within the safe area of its superview, the edge insets in this property are 0.
Use UICollectionView.contentInsetAdjustmentBehavior
Nested view
For UICollectionView inside Cell inside UICollectionView, its insets is 0, but its parent parent is correct, which is the original cell
UICollectionView -> Cell -> ContentView -> UICollectionView
collectionView.superview?.superview?.safeAreaInsets
viewWillAppear: safeAreaInsets is not set to collectionView viewDidAppear: safeAreaInsets is set to collectionView and cells, but not to nested collectionView
In viewSafeAreaInsetsDidChange
, invalidate outer and nested collectionViewLayout
Use extendedLayoutIncludesOpaqueBars
A Boolean value indicating whether or not the extended layout includes opaque bars.
Seems to affect left and right insets
- https://stackoverflow.com/questions/18798792/explaining-difference-between-automaticallyadjustsscrollviewinsets-extendedlayo
- https://medium.com/@wailord/extended-layout-in-ios-pre-ios-11-5eff2debf28
Seemingly related to UIPresentationController
But it’s not, it is because of when safeAreaInsets is available, and how it is passed to nested view
When invalidating collection view layout with custom UIPresentationController
, alongsideTransition
is called twice, the first time with old safeAreaInsets
, and the second time with latest safeAreaInsets
And the layout invalidation uses the old insets.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { _ in
self.collectionViewLayout.invalidateLayout()
})
}
Dispatch
// UIViewController subclass
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { _ in
DispatchQueue.main.async {
self.collectionViewLayout.invalidateLayout()
}
})
}
Call layoutIfNeeded
// UIPresentationController subclass
override var frameOfPresentedViewInContainerView: CGRect {
guard let containerView = containerView else { return .zero }
presentedView?.setNeedsLayout()
presentedView?.layoutIfNeeded()
return ...
Check
Check that UICollectionView or the view you’re working on is in view hierarchy
Check that you’re using code in viewDidLayoutSubviews when safeAreaInsets is known