Threading-Problem wirkt sich auf ios 7 anders aus

8

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%     
BluGeni 23.09.2013, 19:17
quelle

4 Antworten

0

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).

    
vinaut 05.10.2013, 13:09
quelle
6

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.

    
Tricertops 08.10.2013 09:58
quelle
0

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.

    
quellish 08.10.2013 09:37
quelle
0

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.

    
Dan Loughney 11.10.2013 21:17
quelle

Tags und Links