Плохая производительность UIStackView в UICollectionViewCells

Я использую UIStackView к макету UILabels в моем UICollectionViewCell подкласс. Я использую iOS SDK 9.2

Прокрутка представления коллекции происходит плавно, если я не обновляю метки text когда я снимаю их. Однако, если я обновлю их text когда я их снимаю, прокрутка идет очень медленно.

Я сделал очень маленькую демонстрацию, чтобы показать проблему, чтобы запускаться на устройстве (не на симуляторе). Вы можете создать новый пустой проект и заменить содержимое 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")
    }
}

Вы заметите, что прокрутка плавная, когда вы закомментируете вызов fillLabels,

Если вы попытаетесь воспроизвести тот же макет без UIStackViews и включить звонок fillLabelsВы заметите, что прокрутка тоже плавная.

Это предполагает UIStackView страдает узкие места производительности, если он пересчитал свою компоновку.

Верна ли эта гипотеза? Есть ли какие-то решения?

1 ответ

Вы пытались не использовать автоматическую разметку? По моему опыту, автоматическое расположение является виновником производительности во многих ситуациях.

Постарайтесь не устанавливать для translatesAutoresizingMaskIntoConstraints значение false (по умолчанию установлено значение true), а также избавиться от компоновки на основе ограничений самого представления коллекции (вместо этого используйте маски с автоматическим изменением размера).

Другие вопросы по тегам