UICollectionViewAttributes should be able to dictate fitting priorities of elements

Originator:zach
Number:rdar://32082880 Date Originated:09-May-2017 03:32 PM
Status:Open Resolved:false
Product:iOS + SDK Product Version:iOS 10.3 (14E269)
Classification:Enhancement Reproducible:Sometimes
 
Area:
UIKit

Summary:
iOS 8 added incremental layout invalidation and self-sizing to UICollectionViewLayout. iOS 8 also introduced the `systemLayoutSizeFittingSize(_:withHorizontalFittingPriority:verticalFittingPriority:)` layout primitive, which has a clear use case for supporting the former.

Unfortunately, these do not interact by default. Default self-sizing uses the no-arguments version, which is the equivalent of sending the fitting size priority to both axes. In many designs, this is deficient and causes layout ambiguity. At scale, this source of ambiguity leads to a weaker understanding of Auto Layout by the community and, quite frequently, abandonment of self-sizing.

A reusable view can choose to change its implementation by overriding `UICollectionReusableView.preferredLayoutAttributesFitting(_:)`. For instance, a vertically-scrolling list might prefer to pin its width and only express its preferred height. It is lacking this context from the layout. The benefit of the split between UICollectionView, UICollectionReusableView, and UICollectionViewLayout is to reduce coupling. Fixing this problem in the view class creates coupling between a layout and the views displayed within.

This radar serves as a proposal to add `horizontalFittingPriority` and `verticalFittingPriority` to `UICollectionViewLayoutAttributes`, to be consumed appropriately in the default implementation of `UICollectionReusableView.preferredLayoutAttributesFitting(_:)`.

Steps to Reproduce:
In lieu of repro steps, I'll provide some usage examples:

- I have a layout that scrolls only vertically, like a table view. I want cells to be pinned to the width of the collection view's frame minus any padding, and resizing to fit their height in that scenario.
- I have a layout that acts as a horizontally scrolling carousel. I may want to reuse cells from the above layout, but flip the axis they resize on.
- I have an advanced layout that adds carousels to a vertically scrolling UI. (It's per-section modular, like the App Store.) I'd be using the same cells

Expected Results:
As a layout author, I can express to cells the ways they may resize to their preferred layout attributes within my layout.

Actual Results:
As a layout author, I must require all cells that are clients of my layout derive from the same class in order to size correctly.

Version:
iOS 10.3 (14E269)

Notes:
The new attributes would default to `UILayoutPriorityFittingSizeLevel` to preserve the old behavior. 

The default implementation in `UICollectionReusableView.preferredLayoutAttributesFitting(_:)` may choose to conditionalize the new call to `systemLayoutSizeFittingSize(_:withHorizontalFittingPriority:verticalFittingPriority:)` so as to not cause inconsistent behavior across SDKs, but I don't personally think that's needed. A client would likely not conditionalize use of the new layout attribute but continue to use the above workarounds while they support previous deployment targets.

Configuration:
N/A. All configurations.

Attachments:
N/A.

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!