2012-10-12 5 views
5

Ich habe eine Verzögerung für eine bestimmte Zeit und muss trotzdem andere Dinge auf demselben Runloop weiterlaufen lassen. Ich habe den folgenden Code benutzen dies zu tun:Korrekte Art zu verzögern, während die Run-Schleife fortgesetzt werden kann

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 

Dies scheint genau das zu tun, was ich will, außer dass manchmal die Funktion sofort zurück, ohne die gewünschte Wartezeit (1 Sekunde).

Kann mir jemand sagen, was könnte das verursachen? Und was ist der richtige Weg zu warten, während die Run-Schleife laufen darf?

HINWEIS: Ich möchte in einer ähnlichen Weise wie sleep() verzögern, so dass ich nach der Verzögerung wieder im gleichen Ausführungsstream wie zuvor bin.

+0

Was möchten Sie verzögern? Hast du "dispatch_after" angeschaut? –

+0

Ich möchte den aktuellen Thread verzögern, ähnlich wie bei sleep(), außer dass ich möchte, dass der Runloop während dieser Verzögerungszeit weiterläuft (so dass andere Ereignisse und andere Dinge eintreten können). – Locksleyu

Antwort

8

Sie sollten GCD und dispatch_after dafür verwenden. Es ist viel aktueller und effizienter (und Thread-Safe und alle) und sehr einfach zu bedienen.

Es gibt sogar einen Code-Schnipsel in Xcode eingebettet, so dass, wenn Sie dispatch_after Eingabe beginnen wird das Snippet vorschlagen, und wenn Sie es bestätigen die vorbereiteten 2-3 Zeilen für Sie in Ihrem Code schreiben :)

Code Snippet suggestion by Xcode

int64_t delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    <#code to be executed on the main queue after delay#> 
}); 
+1

Die Methode, die Sie erwähnen, führt einen anderen Teil des Codes in der Hauptwarteschlange aus, was ich tun möchte, ist im Grunde genommen für eine gewisse Zeit zu verzögern und zu dem Code zurückzukehren, den ich zuvor ausgeführt habe. Zum Beispiel, wenn ich eine for-Schleife hatte, die einen Druck gemacht hat, dann warte eine Sekunde und wiederhole dann. Ich möchte, dass die Anweisung für eine Sekunde einfach "schläft" und dann zurück zur For-Schleife geht, die ich zuvor ausgeführt habe. Ist das sinnvoll? – Locksleyu

+1

Das macht und macht keinen Sinn. Sie können dies tun, indem Sie Ihren Thread in den Ruhezustand versetzen ('[NSThread sleepForTimeinterval:]' oder 'usleep()'?), Aber dies wird eine aktive Pause machen, die in den richtigen OOP-Programmiermustern nicht empfohlen wird. Und wenn Sie Ihre for-Schleife auf dem Haupt-Runloop ausführen, wird Ihre Anwendung natürlich "eingefroren". Das ist wahrscheinlich ein schlechtes Design. – AliSoftware

+2

Die Lösung, die ich sehe, wenn Sie wirklich N Iterationen ausführen wollen, die jeweils um 1 Sekunde getrennt sind, ist 'for (int i = 0; i AliSoftware

1

Verwenden Sie einen NSTimer, um einen Aufruf einer Methode nach einer gewissen Verzögerung auszulösen.

1

The accepted SO answer here sollte helfen. Sie können auch David's dispatch_afer (explained here) implementieren, was eine modernere Methode ist, dasselbe mit GCD zu machen.

Es gibt mehrere GCD-Funktionen wie diese, die wissenswert sind, und sie sind sehr einfach zu bedienen.

+0

Danke für die Antwort. Das ist aber nicht genau das, was ich suche (Entschuldigung, wenn ich in der Post unklar war). Ich möchte im Grunde meinen aktuellen Thread blockieren (ähnlich einem Schlaf (1)) und dann die Kontrolle dorthin zurückbringen, wo ich vorher war. Der Code, den du verlinkt hast, führt nach einiger Zeit "irgendeinen anderen Code" aus, anstatt nur die Kontrolle an meinen Thread zurückzugeben, damit ich dort fortfahren kann, wo ich aufgehört habe. Das Beispiel, das ich gab, tut dies, außer manchmal nicht richtig zu verzögern. – Locksleyu

0

Haben Sie performSelector:withObject:afterDelay: versucht?

Vom Apple documentation

Ruft eine Methode des Empfängers auf dem aktuellen Thread des Standardmodus nach einer Verzögerung verwendet wird.

0

Ich hatte ein ähnliches Problem und das ist meine Lösung. Hoffe, es funktioniert auch für andere.

__block bool dispatched = false; 
while (put your loop condition here) 
{ 
    if (dispatched) 
    { 
     // We want to relinquish control if we are already dispatched on this iteration. 
     [ [ NSRunLoop currentRunLoop ] runMode: NSDefaultRunLoopMode beforeDate:[ NSDate date ] ]; 
     continue; 
    } 

    // mark that a dispatch is being scheduled 
    dispatched = true; 

    int64_t delayInNanoSeconds = (int64_t) (0.1 * (float) NSEC_PER_SEC); 
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delayInNanoSeconds); 

    dispatch_after(delayTime, dispatch_get_main_queue(), ^() { 
     // Do your loop stuff here 
     // and now ready for the next dispatch 
     dispatched = false; 
    }); 
} // end of while 
Verwandte Themen