7

I'm using UICollectionView with AutoSizing cells which looks similar to UITableView.

As has been mentioned in the previous questions: q1, q2 adopting Self-Sizing cells requires implementing preferredLayoutAttributesFitting(_:) method to apply the sizing with the help of the systemLayoutSizeFitting(_ targetSize:).

However, in the recent WWDC session (High Performance Auto Layout), it was mentioned, that using systemLayoutSizeFitting(_ targetSize:) is expensive as it creates a new AutoLayout engine discards it afterwards, requiring it to solve all the constraints, without caching the previously computed results.

In my app I've implemented self sizing in a fashion proposed in the answers. However, the scrolling performance is terrible in the table-like lists (many rows of small height).

Obviously, calling systemLayoutSizeFitting(_ targetSize:) in a UICollectionViewCell just to calculate its size is expensive and taxing on the CPU (since both the size estimation and the actual layout take place on the main thread).

What would be the recommended way to achieve the following results at the same time

  1. A stall-free scrolling UICollectionView
  2. Make width of the cells fixed and equal to UICollectionView Width minus margins?

What is the recommended strategy to have both, AutoSizing cells and high scrolling performance?

Richard Topchii
  • 4,569
  • 3
  • 27
  • 70

1 Answers1

0

Fixed by adding a width constraint to a base class. Since the preferredLayoutAttributesFitting method was only used for updating a preferred width.

The updateConstraints method is not called every time during the collection scroll, which prevents from constraint churn:

import UIKit
import SnapKit

class AutoSizingCellBase: UICollectionViewCell {
  override class var requiresConstraintBasedLayout: Bool {
    return true
  }

  private var widthConstraint: Constraint?

  override func updateConstraints() {
    if widthConstraint == nil {
      if let window = window {
        let width = window.bounds.width - 16
        contentView.snp.makeConstraints { (make) in
          widthConstraint = make.width.equalTo(width).constraint
        }
      }
    }
    super.updateConstraints()
  }
}

Also, it's possible to constrain the cell to the superview since the updateConstraints method is invoked after the view has been added to the hierarchy.

Richard Topchii
  • 4,569
  • 3
  • 27
  • 70