UICollectionViewFlowLayout's sectionInsetReference = .fromSafeArea produces inconsistent results after rotating on iPhone X

Originator:wes
Number:rdar://34491993 Date Originated:2017-09-18
Status:New Resolved:
Product:UIKit Product Version:iOS 11.0
Classification:Usability Reproducible:Always
 
Summary:
When using UICollectionViewFlowLayout with sectionInsetReference = .fromSafeArea on iPhone X, the layout of cells is in portrait following a rotation to landscape is different for the portrait layout before any rotation has occurred. It appears that the post-rotation portrait layout is not noticing that the left and right safeAreaInsets have reset to 0, and is treating them like they're still set to 44 pts.

Possibly related: I've also observed that in a UICollectionViewController, at the time that `viewSafeAreaInsetsDidChange` is called, the new safeAreaInsets values have been set on self.view, but they have not yet propagated to self.collectionView.

With the following code:

    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        debugPrint("UICollectionViewController viewSafeAreaInsetsDidChange() was called: self.view.safeAreaInsets: \(self.view.safeAreaInsets); self.collectionView.safeAreaInsets: \(self.collectionView!.safeAreaInsets)")
    }

I get the following logs:
1. When the view is initially displayed (in portrait):

UICollectionViewController viewSafeAreaInsetsDidChange() was called: self.view.safeAreaInsets: UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0); self.collectionView.safeAreaInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)

2. When the view rotates to landscape:

UICollectionViewController viewSafeAreaInsetsDidChange() was called: self.view.safeAreaInsets: UIEdgeInsets(top: 0.0, left: 44.0, bottom: 21.0, right: 44.0); self.collectionView.safeAreaInsets: UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)

3. When the view rotates back to portrait:

UICollectionViewController viewSafeAreaInsetsDidChange() was called: self.view.safeAreaInsets: UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0); self.collectionView.safeAreaInsets: UIEdgeInsets(top: 0.0, left: 44.0, bottom: 21.0, right: 44.0)

Notice how at the time this method is called, self.collectionView!.safeAreaInsets always seems to lag.


Steps to Reproduce:

Run the attached project on iPhone X simulator, with iPhone X initially in portrait orientation (first screenshot). Rotate to landscape (second screenshot). Rotate back to portrait (third screenshot).


Expected Results:

Both portrait layouts should be identical; i.e., the first and third screenshots should be the same.

Actual Results:

The post-rotation portrait layout has sections inset by an additional 44 pts on the left and right: the safe area inset applied for landscape layout was not removed when returning to a portrait layout

Version/Build:
Xcode 9 GM, iOS 11.0 simulator for iPhone X

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!