I have an infinite scroll in my UICollectionView and I've noticed that the way I estimate my cell height is the bottleneck of my collection view. It causes some long delays the more I scroll my collection view.
Is there a better way to estimate the heights of my cells?
The cells have different heights because I have a UILabel
in each of them. I assign a NSMutableAttributedStrings of different lengths to those UILabels:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .justified
paragraphStyle.lineSpacing = 5.0
let attributedText = NSMutableAttributedString(string: " \(post.caption)", attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15), .paragraphStyle: paragraphStyle, .baselineOffset: NSNumber(value: 0)])
attributedText.append(NSAttributedString(string: "\n\n", attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 4)]))
let timeAgoDisplay = post.creationDate.timeAgoDisplay()
attributedText.append(NSAttributedString(string: timeAgoDisplay, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14), NSAttributedStringKey.foregroundColor: UIColor.storiesLightGray()]))
captionLabel.attributedText = attributedText
My sizeForItemAt
method. I've noticed that calling dummyCell.layoutIfNeeded()
makes my app very slow once I have more than 200 items in my collection view:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var height: CGFloat = 180
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: height)
let dummyCell = HomePostCell(frame: frame)
dummyCell.post = presenter.posts[indexPath.item]
dummyCell.layoutIfNeeded()
let targetSize = CGSize(width: view.frame.width, height: 5000)
let estimatedSize = dummyCell.systemLayoutSizeFitting(targetSize)
let newHeight = max(height, estimatedSize.height)
return CGSize(width: view.frame.width, height: newHeight)
}
Thanks!