Ich verwende dieses Projekt von github, es ist ein Bilderwähler. Ich musste seit ios7 eine kleine Änderung vornehmen, um die Vorschaubilder aus Ihren Alben wieder anzeigen zu lassen, aber mit dieser Änderung werden jetzt die ausgewählten Fotos (2/5) auf 0 zurückgesetzt, wenn Sie den Picker verlassen und wieder darauf zugreifen / 5 obwohl ich Fotos ausgewählt habe. Wie kann ich das beheben?
Das dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
scheint ewig zu dauern, um das ui sogar mit dispatch_async(dispatch_get_main_queue()
zu aktualisieren, um das ui darin neu zu laden. Wenn ich das dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
auskommentiere, werden die Bilder sofort geladen, aber andere Dinge werden kaputt, die von der Warteschlange abhängen.
Hier ist das Code-Snippet mit dem dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
Ich habe mich mit dem Code verändert, den ich auskommentiert habe
AGIPCAssetsController.m:
%Vor%Ich habe viel Zeit mit diesem Code verbracht und konnte keine richtige Lösung finden. Anscheinend ist das Problem auf GitHub aufgetaucht, und ein Benutzer bot eine Lösung an:
Aber anscheinend hat er nur alle Blöcke entfernt, die im Hintergrund laufen, also nehme ich an, dass für eine große Anzahl von Bildern die Leistung schlecht wäre.
Mein Tipp ist, dass in einem dispatch_async-Block Code ausgeführt wird, der eine UIKit-Funktion aufruft. und somit ist das Verhalten grundsätzlich undefiniert.
Zum Beispiel scheint mir, dass die Funktion setAsset
in AGIPGridItem.m innerhalb der von Ihnen geposteten Dispatch_async aufgerufen wird. Es ruft UImage auf und obwohl es sich in einer Sperre befindet, sollte es immer noch im Hintergrundthread ausgeführt werden, während der gesamte UIKit-Code auf der Haupttask ausgeführt werden sollte.
UITableViewCell lädt Bilder und wiederverwendete Zellen
Aber selbst wenn ich den Aufruf innerhalb von dispatch_async(dispatch_get_main_queue()...)
umgebe, funktioniert es noch nicht.
Es scheint, dass der Aufruf [view removeFromSuperview];
in setItems
in AGIPGriell.m irgendwie verantwortlich ist, aber das Entfernen hat den Nebeneffekt, ein Speicherleck zu erzeugen (nicht überraschend).
AGIPCGridItem
ist eine Unterklasse von UIView
. Arbeiten Sie nicht mit UIKit-Objekten im Hintergrundthread.
Stelle sicher, dass du den Hintergrund-Thread benötigst und wenn du dies tust, lege nur schwere Aufgaben in den Hintergrund. Das Erstellen eines UIView
sollte nicht so sein.
Es wird auch nicht empfohlen, PRIORITY_LOW
use simple PRIORITY_DEFAULT
zu verwenden.
Bearbeiten: Wenn Sie neugierig sind warum es unter iOS 6 funktioniert hat: Das ist das Implementierungsdetail von UIKit. Es war immer noch falsch, aber irgendwie hast du das erwartet.
Die globale Dispatch-Warteschlange ist eine freigegebene Ressource. DISPATCH_QUEUE_PRIORITY_LOW
Tasks werden ausgeführt, nachdem alle anderen Tasks in der Warteschlange mit einer höheren Priorität ausgeführt wurden. Wenn die Warteschlange viele Blöcke mit einer höheren Priorität erhält, wird Ihre DISPATCH_QUEUE_PRIORITY_LOW
-Aufgabe möglicherweise sehr lange nicht ausgeführt!
Dies ist in Concurreny-Programmierhandbuch sowie libdispatch Manpages
Im Grunde genommen sorgen andere Aufgaben mit höherer Priorität dafür, dass die Dinge beschäftigt bleiben und Ihre Aufgabe mit niedriger Priorität keine Gelegenheit erhält.
Ich habe die Antwort von iMartin hervorgehoben. "AGIPCGridItem ist eine Unterklasse von UIView. Funktioniert nicht mit UIKit-Objekten im Hintergrund-Thread." Er hat es.
Ich hatte ein sehr ähnliches Problem, als ich iOS6 auf 7 umstellte. Ich schickte eine ALAsets-Anfrage in einem Hintergrund-Thread. Sobald der Abruf abgeschlossen ist, würde ich die UIImageView, ein UILabel und einen Wrapper erstellen und dann dieses Objekt an den Haupt / Vordergrund-Thread senden, der gerendert werden soll. Dies funktionierte auf iOS6 gut, aber auf 7 war es nicht für etwa 20 Sekunden gezogen. Es würde manchmal nach einem UI-Ereignis wie eine Berührung zeichnen.
Fix war, das ALAsset im Hintergrund zu holen, das an den Hauptthread zu schicken, wo ich die Bildansicht erstellt habe, usw. Funktioniert jetzt wie ein Zauber.