2012-04-13 3 views
1

Ich habe mit meiner iOS-App das seltsamste Verhalten festgestellt. Ich habe diesen Code:Ich rufe dispatch_async mit einem Selektor und einem Ziel auf. Der Selector wird aufgerufen, aber die Benutzeroberfläche wird erst aktualisiert, wenn ich auf die Home-Taste klicke.

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
      CMLog(@"Start Save RoundQuestions Asynchronously"); 
      [round saveRoundQuestions:target selector:selector]; 
     }); 

Diese Funktion beendet es Arbeit ist und nennt dies:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 
     [target performSelector:selector]; 
#pragma clang diagnostic pop 

Die Protokolle zeigen alles richtig läuft, aber das Ziel ruft eine Pushviewcontroller auf einem Navigation, und es dauert ewig Mach den eigentlichen Push. Ich kann es erzwingen, indem ich auf den Home-Button klicke. Ich habe gelesen, dass ich wahrscheinlich die Thread-Sicherheit verletze und die Run-Schleife muss möglicherweise geweckt werden.

Ist es falsch, einen Selektor von einem dispatch_async aufzurufen? Oder muss ich den Selektor für den Hauptthread ausführen, auf dem sich die Benutzeroberfläche befindet?

EDIT: Ich habe das Problem tatsächlich herausgefunden. Es stellte sich heraus, dass ich eine Funktion anrief, die die Benutzeroberfläche innerhalb von saveRoundQuestions blockierte, was meiner Ansicht nach die Push-Animationen sozusagen in den Hintergrund drängte. Ich stelle diese Funktion in den Hintergrund und die Push-Animation passiert jetzt sofort. Aber ich bin immer noch neugierig, warum?

Antwort

1

Sie können die Benutzeroberfläche mit dispatch_async erfolgreich aktualisieren. Nur statt dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) verwenden Sie dispatch get_main_queue()

edit: Nach Ihrem Update. Wenn Sie einige teure Arbeit innerhalb saveRoundQuestions tun, und dann updateUI, sollten Sie verwenden:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     CMLog(@"Start Save RoundQuestions Asynchronously"); 
     [round saveRoundQuestions:target selector:selector]; 
    }); 

Und dann innerhalb von saveRoundQuestions setzen einen weiteren Block in dispatch_get_main_queue() UI zu aktualisieren.

4

Sie sollten nur auf dem Hauptthread UI-Updates tun, so dass Sie die Hauptwarteschlange erhalten müssen mit:

dispatch_get_main_queue() 

statt dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)

Meine Antwort steht noch, gibt es keine Garantie, dass dispatch_get_global_queue woud die Warteschlange für den Haupt-Thread zurück, es ist nur eine Warteschlange mit hoher Priorität

Name: dispatch_get_gl obal_queue
Abstract: Gibt eine bekannte globale gleichzeitige Warteschlange einer bestimmten Prioritätsstufe zurück.

+0

Beide Antworten sind korrekt und funktionieren, aber ich denke, die andere Antwort hat mein Problem ein wenig besser verstanden, weil ich Async wegen des schweren Prozesses in saveRoundQuestions geschickt habe, also werde ich ihn vergeben. Sieht aus, als hättest du trotzdem ein paar Beulen bekommen. :) –

+0

Vielen Dank für beide gute Antworten. Es war ein bisschen ein DOH Moment für mich, da ich wusste, dass es nicht in der Hauptwarteschlange lief. –

Verwandte Themen