简体   繁体   English

UICollectionViewCells中UIStackView的性能不佳

[英]Bad performance of UIStackView within UICollectionViewCells

I am using UIStackView to layout UILabels in my UICollectionViewCell subclass. 我正在使用UIStackView在我的UICollectionViewCell子类中布局UILabels I'm using the iOS SDK 9.2 我正在使用iOS SDK 9.2

The scrolling of the collection view is smooth if I don't update the labels' text when I dequeue them. 如果我在出列标签时不更新标签的text ,则集合视图的滚动是平滑的。 However, if I update their text as I dequeue them, the scrolling is very slow. 但是,如果我在将它们出列时更新它们的text ,则滚动速度非常慢。

I made a very small demo to show the problem, to be ran on a device (not the simulator). 我做了一个非常小的演示来显示问题,在设备(不是模拟器)上运行。 You can create a new empty project and replace the contents of ViewController.swift with this: 您可以创建一个新的空项目并用以下内容替换ViewController.swift的内容:

import UIKit

class ViewController: UIViewController {

    override func loadView() {
        view = UIView()

        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 200)
        let collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: layout)
        collectionView.registerClass(Cell.self, forCellWithReuseIdentifier: "Cell")
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.dataSource = self
        view.addSubview(collectionView)

        let constraints = ["H:|-[collectionView]-|",
            "V:|[collectionView]|"
        ].flatMap { NSLayoutConstraint.constraintsWithVisualFormat($0, options: [], metrics: nil, views: ["collectionView": collectionView])
        }
        NSLayoutConstraint.activateConstraints(constraints)

    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! Cell

        //comment out the line below to make the scrolling smoother: 
        cell.fillLabels()

        return cell
    }
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 100
    }
}

class Cell: UICollectionViewCell {

    var labelArray = [UILabel]()

    func fillLabels() {
        for label in labelArray {
            label.text = "\(label.text!) yo"
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        contentView.backgroundColor = UIColor.whiteColor()

        let stackView = UIStackView()
        stackView.axis = .Horizontal
        stackView.alignment = .Leading
        stackView.distribution = .EqualSpacing
        stackView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(stackView)

        let leftStack = UIStackView()
        leftStack.axis = .Vertical

        let rightStack = UIStackView()
        rightStack.axis = .Vertical

        stackView.addArrangedSubview(leftStack)
        stackView.addArrangedSubview(rightStack)

        for index in 0...10 {
            let leftLabel = UILabel()
            leftLabel.text = "\(index)"
            leftStack.addArrangedSubview(leftLabel)

            labelArray.append(leftLabel)

            let rightLabel = UILabel()
            rightLabel.text = "\(index)"
            rightStack.addArrangedSubview(rightLabel)

            labelArray.append(rightLabel)
        }


        let constraints = [
            "H:|[stackView]|",
            "V:|[stackView]|"
            ].flatMap {
                NSLayoutConstraint.constraintsWithVisualFormat($0, options: [], metrics: nil, views: ["stackView": stackView])
        }

        NSLayoutConstraint.activateConstraints(constraints)

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

You'll notice the scrolling is smooth when you comment out the call to fillLabels . 当您注释掉fillLabels的调用时,您会注意到滚动是平滑的。

If you try to reproduce the same layout without UIStackViews and include the call fillLabels , you'll notice the scrolling is smooth too. 如果您尝试在没有UIStackViews情况下重现相同的布局并包含调用fillLabels ,您会发现滚动也很平滑。

This suggests UIStackView suffers performance bottlenecks if it has recalculate its layout. 这表明如果重新计算其布局, UIStackView会遇到性能瓶颈。

Is this hypothesis correct? 这个假设是否正确? Are there some solutions? 有一些解决方案吗?

Have you tried not using auto layout? 你尝试过不使用自动布局吗? In my experience auto layout is a performance culprit in many situations. 根据我的经验,在许多情况下,自动布局是性能的罪魁祸首。

Try to not set translatesAutoresizingMaskIntoConstraints to false (default is true) and also get rid of the constraint based layout of the collection view itself (use autoresizing masks instead). 尝试不将translatesAutoresizingMaskIntoConstraints设置为false(默认为true),并且还要删除集合视图本身的基于约束的布局(改为使用自动调整掩码)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM