it-swarm.com.de

Was ist der Unterschied zwischen performSelectorOnMainThread und dispatch_async in der Hauptwarteschlange?

Ich hatte Probleme beim Ändern einer Ansicht in einem Thread. Ich habe versucht, eine Unteransicht hinzuzufügen, aber die Anzeige dauerte etwa 6 oder mehr Sekunden. Ich habe es endlich zum Laufen gebracht, weiß aber nicht wie. Also habe ich mich gefragt, warum es funktioniert und was der Unterschied zwischen den folgenden Methoden ist:

//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
    //some UI methods ej
    [view addSubview: otherView];
}

//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
 waitUntilDone:NO];

//Also didnt work: NSNotification methods -  took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
 @"notification-identifier" object:object];

Zu Referenzzwecken wurden diese in diesem Completetion-Handler der Klasse des ACAccountStore aufgerufen.

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

Bearbeiten: Wenn ich sage, dass es nicht funktionierte, bedeutete dies, dass es etwa 6 Sekunden dauerte, um die hinzugefügte Ansicht anzuzeigen. 

52
Miguel Lomelí

Standardmäßig plant -performSelectorOnMainThread:withObject:waitUntilDone: nur, dass der Selektor im Standardmodus ausgeführt wird. Wenn sich die Laufschleife in einem anderen Modus befindet (z. B. im Tracking-Modus), wird sie erst ausgeführt, wenn die Laufschleife wieder in den Standardmodus wechselt. Sie können dies mit der Variante -performSelectorOnMainThread:withObject:waitUntilDone:modes: umgehen (indem Sie alle gewünschten Modi übergeben).

Auf der anderen Seite führt dispatch_async(dispatch_get_main_queue(), ^{ ... }) den Block aus, sobald die Hauptlaufschleife den Steuerungsfluss wieder in die Ereignisschleife zurückgibt. Modi interessiert es nicht. Wenn Sie sich also nicht für Modi interessieren, ist dispatch_async() der bessere Weg.

70
Lily Ballard

Dies liegt wahrscheinlich daran, dass performSelectorOnMainThread:withObject:waitUntilDone: die Nachricht mit den üblichen Laufschleifenmodi in eine Warteschlange stellt. Laut Apples Concurrency-Programmierhandbuch verschachtelt die Hauptwarteschlange in der Warteschlange befindliche Aufgaben mit anderen Ereignissen aus der Laufschleife der App. Wenn also andere Ereignisse in der Ereigniswarteschlange verarbeitet werden sollen, werden die in der Warteschlange befindlichen Warteschlangenblöcke möglicherweise zuerst ausgeführt, obwohl sie später übermittelt wurden.

Dieser Artikel ist eine hervorragende Erklärung für performSelectorOnMainThread vs. dispatch_async, die auch die obige Frage beantwortet.

1
Say2Manuj

Haben Sie das PerformSelectorOnMainThread mit waitUntilDone=YES ausprobiert

Z.B: 

Code:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

Ich denke, das könnte das Problem lösen, weshalb PerformSelectorOnMainThread so lange braucht, um zu antworten.

0
Ruchira Randana