UIWebView im Multi-Thread-ViewController
Habe ich ein UIWebView in einem viewcontroller, der hat zwei Methoden, wie unten beschrieben. Die Frage ist, ob ich pop-out(Tippen Sie auf zurück auf die navigation bar) ist dieser controller, bevor der zweite thread ist fertig, die app stürzt nach [super dealloc], weil "zu erhalten Versucht, die web-sperren aus einem anderen thread als dem Hauptthread oder das web-thread. Dies kann das Ergebnis von aufrufen zu UIKit von einem sekundären thread aus.". Jede Hilfe wäre wirklich zu schätzen.
-(void)viewDidAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(load) object:nil];
[operationQueue addOperation:operation];
[operation release];
}
-(void)load {
[NSThread sleepForTimeInterval:5];
[self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO];
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich hatte die gleiche Lösung, wo eine hintergrund-thread war die Letzte Veröffentlichung, wodurch dealloc der view-controller zu passieren, in einen hintergrund-thread, am Ende mit den gleichen Absturz.
Den oben
[[self retain] autorelease]
würde noch das Ergebnis in die endgültige Version geschehen aus der autorelease-pool der hintergrund-thread. (Es sei denn, es ist etwas besonderes über Veröffentlichungen aus den autorelease-pool, ich bin überrascht, das würde einen Unterschied machen).Fand ich diese, wie meine ideale Lösung, platzieren Sie diesen code in meine view-controller-Klasse:
Dadurch wird sichergestellt, dass die
release
Methode meiner view-controller-Klasse ist immer auf dem Hauptthread ausgeführt.Ich bin ein wenig überrascht, dass bestimmte Objekte, die nur richtig dealloc ' ed vom Haupt-thread nicht schon so etwas gebaut. Naja...
self performSelectorOnMainThread:
zusuper performSelectorOnMainThread:
?dealloc
könnte erwarten, dass alles sofort aufwischen, und es läuft auf einem anderen thread heißt, es wäre asynchron, es sei denn, man verwendetwaitUntilDone:YES
. Probieren Sie es aus, und lassen Sie es uns wissen!Hier ist etwas code zum ausführen UIKit Elemente auf der Haupt-thread. Wenn Sie arbeiten auf einem anderen thread und ausführen müssen, um ein Stück des UIKit-code, setzen Sie ihn einfach zwischen die Klammern von Grand Central Dispatch snippet.
In der Regel sollten Sie kündigen, jede hintergrund-Operationen, wenn die Ansicht, die Sie verwendet ist Weg. In:
cancelAllOperations
nicht automatisch Abbruch bereits ausgeführten Operationen. Was Sie tun müssen, ist in Ihremload
- Methode, nachdem der thread schlafen, überprüfen Sie dieisCancelled
Eigenschaft der operation; wenn ja, zurück ohne Aufrufdone
. Aber wenn alles, was Sie tun, ist einfach nur Pause in einem hintergrund-thread, ein einfacher Weg, dies zu tun ist mitperformSelector:withObject:afterDelay:
.Ich habe derzeit ein ähnliches problem in meiner Anwendung. Ein view-controller zeigt eine UIWebView geschoben wird, um ein navigation-controller und startet einen hintergrund-thread, um Daten abzurufen. Wenn Sie die Schaltfläche " zurück, bevor der thread beendet ist, stürzt die Anwendung ab mit der gleichen Fehlermeldung.
Das problem scheint zu sein, dass
NSThread
behält das Ziel (selbst) und Objekt (argument) und gibt es, nachdem die Methode ausgeführt wurde-leider gibt er sowohl aus dem thread. Also wenn der controller erzeugt wird, der retain-count ist 1, wenn der thread gestartet wird, der controller bekommt einen retain count von 2. Wenn Sie aus dem pop-controller, bevor der thread erledigt ist, wird der navigation controller Versionen der controller, die Ergebnisse in einem retain count von 1. So weit ist das in Ordnung-Aber wenn der thread endlich beendet,NSThread
Versionen der controller, die Ergebnisse in einem retain count von 0 und eine sofortige dealloc innerhalb des thread. Dies macht die UIWebView (veröffentlicht in der dealloc-Methode der controller -) Erhöhung, die thread-Warnung-Ausnahme und Absturz.Habe ich erfolgreich gearbeitet, um dieses durch die Verwendung
[[self retain] autorelease]
als Letzte Anweisung in dem thread (bevor der thread wieder freigegeben pool). Dies stellt sicher, dass das controller-Objekt wird nicht sofort freigegeben, sondern markiert, wie autoreleased und freigegeben werden später in der main-thread die run loop. Dies ist jedoch ein etwas schmutziger hack und ich würde lieber eine bessere Lösung zu finden.Habe ich versucht :
scheint sogar noch besser funktionieren.
Ich bin mir nicht sicher, was da genau Los ist, basierend auf deinem code, aber es sieht aus wie viewDidAppear wird immer angerufen und das erstellen der zweite thread, und dann bist du der Navigation Weg von der Steuerung und loslassen, und dann der zweite thread beendet und fordert performSelectorOnMainThread auf das freigegebene Objekt "selbst". Ich glaube, Sie können einfach brauchen, um zu überprüfen, dass die Veröffentlichung nicht stattgefunden hat?
Die Fehlermeldung, die Sie bekommen, bedeutet, dass Sie einige UIKit code aus deinem zweiten thread. Apple vor kurzem Hinzugefügt einige Prüfungen für Gewinde-Aufrufe UIKit, und ich denke, Sie brauchen wahrscheinlich nur zum umgestalten von load-Funktion zum aktualisieren der Benutzeroberfläche auf dem Haupt-thread, anstatt zu telefonieren UIWebView Funktionen aus dem zweiten thread.
Hoffe, das hilft!
Ich habe versucht, beide Lösungen oben geschrieben
[operationQueue cancelAllOperations]
, und[[self retain] autorelease]
. Jedoch, mit quick-Klick, es gibt immer noch Fälle, wo der retain-count fällt auf 0 und die Klasse wird aufgehoben für den zweiten thread. Um zu vermeiden, ein Absturz, habe ich die folgenden in meinemdealloc
für jetzt:was eine offensichtliche Leck, scheint aber das kleinere von 2 übeln.
Jede weitere Erkenntnis von irgendjemand dieses problem Auftritt, ist willkommen.