2017-06-16 2 views
2

Es gibt viele Fragen zum asynchronen Laden von Bildern und anderen heruntergeladenen Daten. Es gibt jedoch keine Fragen zum asynchronen Laden dieser Bilder (sobald sie heruntergeladen wurden) in die Benutzeroberfläche.Laden Sie alle Zelleninhalte asynchron

Ich versuche 60 fps Scrollen auf meinem UICollectionView zu erreichen, obwohl ich nach einer Lösung suche, die für alle Ansichten funktioniert.

Wenn ich zum Beispiel Bilder in meinem Assets-Ordner habe, die ich in ein schnell scrollendes UIScrollView laden möchte, dauert es einige Zeit, bis sie in den Speicher geladen und auf der Benutzeroberfläche gezeichnet wurden. Gibt es eine Möglichkeit, diese Bilder zuerst im Speicher zwischenzuspeichern (ohne dabei den Speicher zu beschädigen/zu viel zu verwenden) und sie dann in die Zellen zu laden, sobald sie im Speicher zwischengespeichert sind?

Wie ich es jetzt verstehen, wenn ich sage,

cell.imageView.image = UIImage(named: "grapes") 

das Vermögen Ordner grapes geöffnet und gelesen von, und dann bringt sie das entsprechende Bild (1x, 2x oder 3x) in dem Speicher. Nachdem das korrekte Bild in den Speicher geladen wurde, wird ihm cell.imageView.image zugewiesen und dann wird das Bild gezeichnet. Ist das genau? Tritt das alles im Hauptthread auf? Wenn ja, hat das nicht die Möglichkeit, den Haupt-Thread zu verstopfen und das Gerät dazu zu bringen, einige Frames zu überspringen?

Ich gehe davon aus, dass ein ähnlicher Prozess auftritt, wenn Sie zum Beispiel komplexe Ausdrücke lösen oder Text formatieren. Wenn ja, kann und wie erstelle ich den Inhalt, der asynchron geladen werden soll, damit der Hauptthread nicht verstopft wird (selbst auf Kosten temporär leerer Inhaltsansichten)?

+0

@Rob, meinst du, dass das UIImageView mehr Operationen für die Skalierung oder etwas anderes ausführen muss? – IHaveAQuestion

+0

Ich habe über eine Bildansicht gesprochen, also 40x40 Punkte, aber Sie verwenden ein Bild mit 1200x1200 Pixel und verwenden einen Inhaltsmodus '.scaleAspectFit' oder' .scaleAspectFill'. Wirklich jede Situation, in der du dich auf contentMode verlässt, um dein Bild angemessen zu skalieren. Oder natürlich, wenn Sie Ihre eigenen Scaling/Cropping Routinen aufrufen. – Rob

Antwort

0

erstellen Bild auf den Hintergrund, setzen Sie auf UI-Thread:

DispatchQueue.global(qos: .background).async { 
    let image = UIImage(named: "image") 

    DispatchQueue.main.async { 
     cell.imageView.image = image 
    } 
} 

Das Beispiel vereinfacht ist, müssen Sie kümmern sich um Scrollen und Zelle reusage.

+0

Ich dachte, dass alle Dinge, die die Benutzeroberfläche ändern, auf dem Hauptthread passieren müssen? – IHaveAQuestion

+0

@IHaveAQuestion das ist keine Benutzeroberfläche, sollten Sie nicht UI-Strukturansicht auf Hintergrundthreads ändern, aber Sie können alles, was Sie wollen, laden –

+0

Awesome, thanks! Warum stellst du auch alles in diesen Block? Das heißt, was ist der Unterschied zwischen '.global (qos: .background) .async' und' .main.async'? – IHaveAQuestion

1

Ja, es kann einige Millisekunden dauern, um den Speicher zu laden und zu speichern. Es kann sich besonders auf das Erlebnis auswirken, wenn das Bild nicht die passende Größe für die Benutzeroberfläche hat (z. B. verlassen Sie sich auf contentMode von etwa scaleAspectFit oder .scaleAspectFill, um die Bildgröße entsprechend anzupassen oder wenn Sie die Größe manuell anpassen). Das kann eher harmlos zu etwas führen, das überraschend rechenintensiv ist.

Im Allgemeinen ist es nicht genug, um problematisch zu sein, aber es kann verhindern, dass Sie optimale 60 fps erreichen. Wenn Sie eine optimale Leistung wünschen, führen Sie möglicherweise einen asynchronen Abruf durch und kombinieren diesen mit table view prefetching oder collection view prefetching.

Re komplexe Ausdrücke und Textformatierung, das ist unwahrscheinlich, dass jemals eine Verzögerung von 60 fps zu verhindern. Aber rate nicht (re this oder images). Sie sollten fps von "release" -Build (mit aktivierten Optimierungen) über Instrumente analysieren und sehen, welche, wenn beide davon beobachtbare Auswirkungen auf fps haben. Testen Sie Ihre physischen Zielgeräte, nicht den Simulator, denn es wäre schade, wenn Sie Zeit verschwenden, um ein Problem, das auf physischen Geräten nicht auftritt, vorzeitig zu optimieren.

+0

Würden einfache UIView-Animationen in den Zellen auch die Bildrate verlangsamen? – IHaveAQuestion

+0

Ich würde vorschlagen, dass Sie aufhören zu erraten, was fps möglicherweise beeinflussen könnte und empirisch validieren (mit optimierten, Release-Builds), was tatsächlich tut. "Vorzeitige Optimierung ist die Wurzel allen Übels. Dennoch sollten wir unsere Chancen in diesen kritischen 3% nicht aufgeben." Stellen Sie sicher, dass Sie in diesen 3% sind, bevor Sie zu viel Schlaf verlieren. Aber als Antwort auf Ihre Frage, nein, einfache Animationen können sich nicht nachteilig auf fps auswirken, obwohl komplexe (z. B. das Animieren von komplexen Ansichtshierarchien mit Gaußschen Unschärfen/Schatten). – Rob

Verwandte Themen