UIWebView in Multithread ViewController

8

Ich habe ein UIWebView in einem Viewcontroller, der zwei Methoden wie folgt hat. Die Frage ist, ob ich diesen Controller herausspringe (auf die Navigationsleiste tippe), bevor der zweite Thread fertig ist, stürzt die App nach [Super Dealloc] ab, weil "versucht wurde, die Websperre von einem anderen Thread als dem Hauptthread zu erhalten Der Web - Thread. Dies kann ein Ergebnis des Aufrufs von UIKit von einem sekundären Thread sein. Jede Hilfe würde wirklich geschätzt werden.

%Vor%     
Tao 03.06.2009, 14:27
quelle

8 Antworten

35

Ich hatte die gleiche Lösung, bei der ein Hintergrundthread die letzte Version war, was dazu führte, dass der Dealloc des View-Controllers in einem Hintergrundthread mit dem gleichen Absturz endete.

Das obige [[self retain] autorelease] würde immer noch dazu führen, dass die endgültige Freigabe aus dem Autorelease-Pool des Hintergrundthreads erfolgt. (Es sei denn, es gibt etwas Besonderes an Releases aus dem Autorelease-Pool, ich bin überrascht, dass dies einen Unterschied machen würde).

Ich fand dies als meine ideale Lösung, indem ich diesen Code in meine View-Controller-Klasse platziere:

%Vor%

Dies stellt sicher, dass die Methode release meiner View-Controller-Klasse immer im Hauptthread ausgeführt wird.

Ich bin ein wenig überrascht, dass bestimmte Objekte, die nur vom Hauptthread korrekt freigegeben werden können, nicht schon so etwas eingebaut haben. Nun gut ...

    
Matt Connolly 28.11.2010, 20:53
quelle
12

Hier ist ein Code zum Ausführen von UIKit-Elementen im Hauptthread. Wenn Sie an einem anderen Thread arbeiten und einen UIKit-Code ausführen müssen, fügen Sie ihn einfach in die Klammern dieses Grand Central Dispatch-Snippets ein.

%Vor%     
Emile Khattar 13.04.2012 01:27
quelle
1

Im Allgemeinen sollten Sie alle Hintergrundoperationen abbrechen, wenn die Ansicht, die sie verwendet, verschwindet. Wie in:

%Vor%     
Denis Hennessy 03.06.2009 14:52
quelle
1

Ich habe derzeit ein ähnliches Problem in meiner Anwendung. Ein View-Controller, der ein UIWebView anzeigt, wird an einen Navigations-Controller gesendet und startet einen Hintergrund-Thread, um Daten abzurufen. Wenn Sie die Zurück-Schaltfläche drücken, bevor der Thread beendet ist, stürzt die Anwendung mit derselben Fehlermeldung ab.

Das Problem scheint zu sein, dass NSThread das Ziel (self) und das Objekt (argument) beibehält und es nach der Ausführung der Methode wieder freigibt - unglücklicherweise gibt es beide aus dem Thread heraus. Wenn also der Controller erstellt wird, ist die Retain-Anzahl 1, wenn der Thread gestartet wird, erhält der Controller eine Retain-Anzahl von 2. Wenn Sie den Controller beenden, bevor der Thread fertig ist, gibt der Navigationscontroller den Controller frei Behalte die Anzahl von 1. Bis jetzt ist das in Ordnung - Aber wenn der Thread schließlich beendet ist, gibt NSThread den Controller frei, was zu einem Retain-Zähler von 0 und einem sofortigen Dealloc innerhalb des Threads führt. Dies führt dazu, dass das UIWebView (das in der Dealloc-Methode des Controllers freigegeben wird) diese Threadwarnungsausnahme auslöst und abstürzt.

Ich habe erfolgreich daran gearbeitet, indem ich [[self retain] autorelease] als letzte Anweisung im Thread verwendete (kurz bevor der Thread seinen Pool freigibt). Dies stellt sicher, dass das Controller-Objekt nicht sofort freigegeben wird, sondern später in der Lauf-Schleife des Haupt-Threads als automatisch freigegeben markiert und freigegeben wird. Allerdings ist dies ein etwas schmutziger Hack und ich würde lieber eine bessere Lösung finden.

    
Zargony 31.07.2009 14:11
quelle
1

Ich habe es versucht:

%Vor%

das scheint noch besser zu funktionieren.

    
thomas 27.09.2010 16:06
quelle
0

Ich bin mir nicht sicher, was genau auf Ihrem Code basiert, aber es sieht so aus, als ob viewDidAppear aufgerufen wird und den zweiten Thread erstellt. Dann navigieren Sie vom Controller weg und lassen ihn los, und dann wird der zweite Thread beendet und ruft performSelectorOnMainThread auf dem freigegebenen Objekt "self" auf. Ich denke, Sie müssen nur überprüfen, ob die Veröffentlichung nicht stattgefunden hat?

Die Fehlermeldung, die Sie erhalten, impliziert, dass Sie einen UIKit-Code aus Ihrem zweiten Thread ausführen. Apple hat kürzlich einige Checks für Threaded-Aufrufe an UIKit hinzugefügt, und ich denke, dass Sie Ihre Ladefunktion wahrscheinlich nur umstrukturieren müssen, um die Benutzeroberfläche im Hauptthread zu aktualisieren, anstatt UIWebView-Funktionen aus dem zweiten Thread aufzurufen.

Hoffe das hilft!

    
Ben Gotow 03.06.2009 20:33
quelle
0

Ich habe beide oben genannten Lösungen ausprobiert, [operationQueue cancelAllOperations] und [[self retain] autorelease] . Es gibt jedoch immer noch Fälle, in denen die Retain-Anzahl auf 0 fällt und die Klasse für den sekundären Thread freigegeben wird. Um einen Absturz zu vermeiden, stelle ich in meinem dealloc vorerst folgendes:

%Vor%

Das ist ein offensichtliches Leck, scheint aber das kleinere Übel zu sein.

Jeder zusätzliche Einblick von jedem, der auf dieses Problem stößt, ist willkommen.

    
Patrick O'Shaughnessey 11.09.2009 03:21
quelle
0
%Vor%     
guangyuanbai 13.09.2012 09:18
quelle