Плохая производительность 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), а также избавиться от компоновки на основе ограничений самого представления коллекции (вместо этого используйте маски с автоматическим изменением размера).