Używam UIStackView
do layoutu UILabels
w mojej podklasie UICollectionViewCell
. Używam pakietu iOS SDK 9.2Zła wydajność UIStackView w ramach UICollectionViewCells
Przewijanie widoku kolekcji jest płynne, jeśli nie zaktualizuję etykiet "text
, gdy je usuń. Jeśli jednak zaktualizuję ich text
po ich usunięciu, przewijanie będzie bardzo powolne.
Zrobiłem bardzo małe demo, aby pokazać problem, który należy uruchomić na urządzeniu (nie symulator). Można utworzyć nowy pusty projekt i zastąpić zawartość ViewController.swift
z tym:
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")
}
}
Zauważysz przewijanie jest płynne podczas wykomentuj wezwanie do fillLabels
.
Jeśli spróbujesz odtworzyć ten sam układ bez UIStackViews
i dołączyć wywołanie fillLabels
, zauważysz, że przewijanie jest również płynne.
Sugeruje to, że w przypadku ponownego obliczenia układu wystąpiły problemy z wydajnością.
Czy ta hipoteza jest poprawna? Czy są jakieś rozwiązania?
Cześć Eric! Czy byłeś w stanie znaleźć jakiekolwiek wnioski na ten temat? – damirstuhec
Nie, zgłoszono błąd: https://openradar.appspot.com/24206043 – Eric
Czy masz włączoną opcję wstępnego pobierania w Inspektorze atrybutów dla UICollectionView – Balanced