2016-01-15 6 views
12

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?

+0

Cześć Eric! Czy byłeś w stanie znaleźć jakiekolwiek wnioski na ten temat? – damirstuhec

+1

Nie, zgłoszono błąd: https://openradar.appspot.com/24206043 – Eric

+0

Czy masz włączoną opcję wstępnego pobierania w Inspektorze atrybutów dla UICollectionView – Balanced

Odpowiedz

0

Czy próbowałeś nie używać automatycznego układu? Z mojego doświadczenia wynika, że ​​auto layout jest sprawcą wydajności w wielu sytuacjach.

Staraj się nie ustawiać translatesAutoresizingMaskIntoConstraints na false (domyślnie jest to prawda), a także pozbyć się układu opartego na ograniczeniach samego widoku kolekcji (użyj zamiast tego maski z funkcją autorezjowania).