Je suis sous-classement EDIT: strong>
Voici les changements que j'ai proposés dans la méthode J'ai calculé le décalage de la collectionView et l'a utilisé pour calculer Les cellules qui seront visibles à l'écran (à l'aide de la hauteur / de la largeur de chaque cellule). Je devais ajouter des cellules supplémentaires de chaque côté afin que lorsque l'utilisateur défile, il n'y a pas de cellules manquantes. J'ai testé cela et la performance va bien. P> p> uicollectionviewflowlayout code> afin de faire défiler deux choses dans un
uicollectionview code>. Le défilement fonctionne bien pour un nombre réduit de comptage de rangée et de section (100-200 rangées et sections), mais il existe un décalage visible lors du défilement lorsque j'augmente la ligne et la section comptent sur 500 c'est-à-dire 250 000 ou plus de cellules dans le
uicollectionview code >. J'ai tracé la source du décalage pour être en boucle dans le
LayoutaTtributesforelementsinrect code>. J'utilise un dictionnaire
pour enfoncé
uicollectionviewlayouttattributes code> de chaque cellule pour éviter de la recalculer et de boucler à travers elle pour renvoyer les attributs des cellules de
Layoutetattributesforelementsinrect code>
LayoutaTtributesforelementsinrect code>. P>
3 Réponses :
Vous devez trouver une structure de données pour vos cellules commandée par dimension (s), afin de proposer un algorithme à l'aide de ces dimensions (s) pour réduire la plage de recherche.
Prenons le cas d'une table avec des cellules 100 pixels hauts par la largeur complète de la vue et 250_000 éléments, demandées aux cellules intersectant {0, haut, 320, bas}. Ensuite, votre structure de données serait une matrice commandée par la coordonnée supérieure et l'algorithme d'accompagnement serait comme p> ajoutez autant de complexité que votre mise en page réelle nécessite. P> < / p>
Par exemple, un tableau imbriqué: P> cellattrsdictionner code> est inapproprié de stocker le
uicollectionviewlayouttattributes code>. Il est indexé par
nsindexpath code> mais dans
Layoutetattributesforelementsinrect code> Vous recherchez une zone. Si vous avez besoin
cellattrsdictionner code> pour autre chose, vous pouvez le laisser mais stocker chaque cellattribute
allCellAttributes[5]
allCellAttributes[6]
En tirant parti des Edit: J'ai ajouté le BiggerRect afin que les attributs puissent être pré-calculés avant avant le défilement là. De votre édition, on dirait que vous cachez toujours les attributs que je ne pense pas être nécessaire pour la performance. En outre, cela va conduire à une empreinte de mémoire beaucoup plus grande avec plus vous faites défiler. Y a-t-il également une raison pour laquelle vous ne voulez pas utiliser le LayoutaTtributesForelementsIrect (rect: CGRRECT) CODE> Avec votre taille de cellule connue, vous n'avez pas besoin de cacher vos attributs et de les calculer pour un
rect code > Comme la collectionView les demande. Vous auriez toujours besoin de vérifier les cas de frontière de 0 et le nombre maximum de section / rangée pour éviter de calculer des attributs inutiles ou non valides, mais cela peut être facilement effectué dans
où code> clauses autour des boucles. Voici un exemple de travail que j'ai testé avec 1000 sections x 1000 rangées et cela fonctionne simplement sans être à la traîne sur le périphérique:
CGRACT CODE> à partir du rappel plutôt que de calculer manuellement l'un de la contentoffset? P>
class LuckGameCollectionViewLayout: UICollectionViewFlowLayout {
let CELL_HEIGHT = 50.0
let CELL_WIDTH = 50.0
override func collectionViewContentSize() -> CGSize {
let contentWidth = Double(collectionView!.numberOfItemsInSection(0)) * CELL_WIDTH
let contentHeight = Double(collectionView!.numberOfSections()) * CELL_HEIGHT
return CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let biggerRect = rect.insetBy(dx: -2048, dy: -2048)
let startIndexY = Int(Double(biggerRect.origin.y) / CELL_HEIGHT)
let startIndexX = Int(Double(biggerRect.origin.x) / CELL_WIDTH)
let numberOfVisibleCellsInRectY = Int(Double(biggerRect.height) / CELL_HEIGHT) + startIndexY
let numberOfVisibleCellsInRectX = Int(Double(biggerRect.width) / CELL_WIDTH) + startIndexX
var attributes: [UICollectionViewLayoutAttributes] = []
for section in startIndexY..<numberOfVisibleCellsInRectY
where section >= 0 && section < self.collectionView!.numberOfSections() {
for item in startIndexX..<numberOfVisibleCellsInRectX
where item >= 0 && item < self.collectionView!.numberOfItemsInSection(section) {
let cellIndex = NSIndexPath(forItem: item, inSection: section)
if let attrs = self.layoutAttributesForItemAtIndexPath(cellIndex) {
attributes.append(attrs)
}
}
}
return attributes
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
let xPos = Double(indexPath.row) * CELL_WIDTH
let yPos = Double(indexPath.section) * CELL_HEIGHT
let cellAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
return cellAttributes
}
}
Pouvez-vous vérifier ma mise à jour avec la solution que j'ai proposée et des commentaires à ce sujet.
Toute suggestion sur l'obtention de cela pour travailler pour une largeur de cellule différente? Merci!
@Unikorn Si vous voulez avoir différentes largeurs de cellules pour chaque cellule, il est certainement plus difficile. Vous pouvez éventuellement enregistrer les attributs dans le dictionnaire comme dans l'exemple original de la question ci-dessus, mais cela augmenterait l'empreinte mémoire, ou stockerait le décalage X pour chaque section (ligne dans ce cas) qui incrèterait à mesure que l'utilisateur traîne vers la droite ou des décréments lors du glissement vers la gauche et est calculé en fonction de la largeur totale des cellules visibles plus l'espacement des cellules. Je suis sûr qu'il y aurait des problèmes avec cela qui auraient besoin d'explorer plus loin, mais cela pourrait être un début.
Évidemment, la boucle à travers le dictionnaire est la partie chère. Je me demande s'il y a quelque part pour clés de votre dictionnaire afin que vous puissiez obtenir tout ce qui se croisit avec un record sans avoir besoin de boucler à travers 250 000 valeurs.
@Kevinditraglia J'ai réfléchi à cela aussi, mais le problème est que
Layoutetattributesforelementsinrect code> ne renvoie pas nécessairement que les éléments visibles. De la doc ( développeur.apple.com/ Bibliothèque / iOS / Documentation / Windowsviews / ... )
Basé sur la position de défilement actuelle, la vue Collection appelle ensuite votre layouTatributesForelementsInrect: méthode pour demander les attributs des cellules et des vues dans un rectangle spécifique, qui peut être ou non le même que le rectangle visible. code>