Sichtbare Verzögerung beim Scrollen durch zweiseitiges Scrollen UICollectionView mit einer großen Anzahl von Zellen (250.000 oder mehr)

8

Ich unterteile UICollectionViewFlowLayout , um in zwei Richtungen in einem UICollectionView zu scrollen. Das Scrollen funktioniert gut für eine kleinere Anzahl von Zeilen- und Abschnittszählungen (100-200 Zeilen und Abschnitte), aber es gibt eine sichtbare Verzögerung während des Scrollens, wenn ich die Anzahl der Zeilen und Abschnitte über 500 d. H. 250.000 oder mehr Zellen in UICollectionView erhöhe. Ich habe die Quelle der Verzögerung für in Schleife in layoutAttributesForElementsInRect verfolgt. Ich verwende ein Dictionary , um UICollectionViewLayoutAttributes jeder Zelle zu behalten, um zu vermeiden, dass es neu berechnet wird und es durchläuft, um Attribute von Zellen von layoutAttributesForElementsInRect

zurückzugeben %Vor%

Bearbeiten: Im Folgenden sind die Änderungen aufgeführt, die ich in der layoutAttributesForElementsInRect -Methode gefunden habe.

%Vor%

Ich habe den Offset der collectionView berechnet und verwendet, um die Zellen zu berechnen, die auf dem Bildschirm sichtbar sind (mit Höhe / Breite jeder Zelle). Ich musste auf jeder Seite zusätzliche Zellen hinzufügen, damit beim Scrollen keine Zellen fehlen. Ich habe das getestet und die Leistung ist in Ordnung.

    
Manish Kumar 30.05.2016, 08:15
quelle

3 Antworten

4

Indem Sie die layoutAttributesForElementsInRect(rect: CGRect) mit Ihrer bekannten Zellengröße ausnutzen, müssen Sie Ihre Attribute nicht zwischenspeichern und können sie nur für eine gegebene rect berechnen, wenn die collectionView sie anfordert. Sie müssten immer noch nach den Grenzfällen von 0 und den maximalen Abschnitts- / Zeilenzählwerten suchen, um zu vermeiden, dass unnötige oder ungültige Attribute berechnet werden, aber das kann leicht in where -Klauseln um die Schleifen getan werden. Hier ist ein funktionierendes Beispiel, das ich mit 1000 Sektionen x 1000 Zeilen getestet habe und es funktioniert ohne Verzögerung auf dem Gerät:

Bearbeiten: Ich habe den biggerRect hinzugefügt, so dass Attribute vorberechnet werden können, bevor das Scrollen dorthin gelangt. Von Ihrer Bearbeitung an sieht es so aus, als würden Sie immer noch die Attribute zwischenspeichern, die meiner Meinung nach nicht für die Performance benötigt werden. Außerdem wird es zu einem viel größeren Speicherbedarf mit mehr Scrollen führen. Gibt es auch einen Grund, warum Sie nicht die angegebene CGRect aus dem Callback verwenden möchten, anstatt manuell eine aus dem contentOffset zu berechnen?

%Vor%     
Dallas Johnson 02.06.2016, 23:20
quelle
1

Sie müssen eine Datenstruktur für Ihre Zellen erstellen, die nach Dimension (en) sortiert ist, um einen Algorithmus zu finden, der diese Dimension (en) verwendet, um den Suchbereich einzugrenzen.

Nehmen wir den Fall einer Tabelle mit Zellen, die 100 Pixel hoch sind und um die gesamte Breite der Ansicht, und 250.000 Elementen, die nach Zellen gefragt werden, die {0, oben, 320, unten} schneiden. Dann wäre Ihre Datenstruktur ein Array, das nach der obersten Koordinate geordnet ist, und der zugehörige Algorithmus wäre wie

%Vor%

Fügen Sie so viel Komplexität hinzu, wie Ihr tatsächliches Layout erfordert.

    
Alex Curylo 01.06.2016 18:43
quelle
1

cellAttrsDictionary ist nicht zum Speichern von UICollectionViewLayoutAttributes geeignet. Es ist indiziert von NSIndexPath , aber in layoutAttributesForElementsInRect suchen Sie nach einem Bereich. Wenn Sie cellAttrsDictionary für etwas anderes benötigen, können Sie es belassen, aber jedes cellAttribute zusätzlich in einer anderen Datenstruktur speichern, die schneller zu durchsuchen ist.

Zum Beispiel ein geschachteltes Array:

%Vor%

Das Array der ersten Ebene beschreibt einen Bereich, sagen wir, es ist in Blöcken von 1000 Pixel Höhe und voller Bildschirmbreite. Also gehen alle cellAttributes, die sich mit dem Rechteck {0, 0, screenwidth, 1000} schneiden, in:

%Vor%

Alle cellAttributes, die sich mit dem Rechteck {0, 1000, screenwidth, 2000} schneiden, gehen in:

%Vor%

Und so weiter ...

Dann können Sie in layoutAttributesForElementsInRect in dieser Datenstruktur suchen, indem Sie abhängig vom angegebenen CGRect direkt in das Array springen. Wenn das Rect z.B. {0, 5500, 100, 6700} dann müssen Sie nur in diesem Bereich suchen:

%Vor%

Das sollte dir die Grundidee geben, ich hoffe du verstehst was ich meine.

    
Darko 02.06.2016 20:07
quelle