UICollectionView in landscape on iPhone X

Having the same issue. This worked for me:

override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        collectionView?.contentInsetAdjustmentBehavior = .always
    }
}

The documentation for the .always enum case says:

Always include the safe area insets in the content adjustment.

This solution works correctly also in the case the phone is rotated.


Thanks to above for help. For my UICollectionViewController subClass, I added the following to viewDidLoad() (Swift 3):

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
    if #available(iOS 11.0, *) {
        flowLayout.sectionInsetReference = .fromSafeArea
    }
}

While Nathan is correct about the versatility of UICollectionView with various layouts, I was mainly concerned about the "default" case where one is using UICollectionViewFlowLayout.

Turns out, iOS 11 has added a sectionInsetReference property to UICollectionViewFlowLayout. The official documentation on it currently lacks a description, however the headers describe it as

The reference boundary that the section insets will be defined as relative to. Defaults to .fromContentInset.

NOTE: Content inset will always be respected at a minimum. For example, if the sectionInsetReference equals .fromSafeArea, but the adjusted content inset is greater that the combination of the safe area and section insets, then section content will be aligned with the content inset instead.

The possible values are

@available(iOS 11.0, *)
public enum UICollectionViewFlowLayoutSectionInsetReference : Int {
    case fromContentInset
    case fromSafeArea
    case fromLayoutMargins
}

and setting it to .fromSafeArea produces the desired results, i.e., when initially in portrait orientation:

initial portrait layout

then when rotating to landscape, the cells are inset such that they are entirely within the safe area:

iPhone X landscape collection view layout

... HOWEVER, there's currently a bug, and when rotating back to portrait after the view has been in landscape, it continues to act as if the left/right safeAreaInsets are set to the landscape values:

portrait layout following rotation from landscape

I've filed a radar (rdar://34491993) regarding this issue.