Faster way to estimate cell height in a CollectionView

可紊 提交于 2019-12-05 06:09:34

问题


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!


回答1:


Ideally you should not use systemLayoutSizeFitting in your sizeForItemAt, because, as you say, it is slow.

You could precache some cell data, calculate the sizes, and store them in an array or similar, so that sizeForItemAt merely has to do the lookup in the array — which is fast.

And you don't really need to use systemLayoutSizeFitting, either; you can use your knowledge of the label size and contents to calculate the size (e.g. using NSAttributedString measurement methods).

That is what we used to do before systemLayoutSizeFitting or auto layout existed, and it remains far faster.



来源:https://stackoverflow.com/questions/50518955/faster-way-to-estimate-cell-height-in-a-collectionview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!