2013-03-11 6 views
57

Ich muss eine Verzögerung zwischen der Ausführung von zwei Zeilen in einer (gleichen) Funktion hinzufügen. Gibt es dafür günstige Möglichkeiten?Hinzufügen einer Verzögerung zwischen der Ausführung von zwei folgenden Zeilen

Hinweis: Ich brauche nicht zwei verschiedene Funktionen, um dies zu tun, und die Verzögerung darf die Ausführung anderer Funktionen nicht beeinflussen.

zB:

line 1: [executing first operation]; 

line 2: Delay      /* I need to introduce delay here */ 

line 3: [executing second operation]; 

Jede Hilfe ist spürbar. Vielen Dank im Voraus ...

Antwort

149

Sie gcd verwenden können, dies zu tun, ohne eine andere Methode

double delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    NSLog(@"Do some work"); 
}); 
01 zu schaffen, die

Sie noch sich stellen sollten „brauche ich wirklich eine Verzögerung hinzuzufügen“, wie es oft Code und verursachen Bedingungen Rennen

4.0+
+2

Es ist richtig, Leute davor zu warnen, aber wenn Sie Code-Controller programmieren, die auf ein externes Gerät mit einer festen Verarbeitungszeit warten müssen, ist das NICHT sinnlos. – user2161301

+2

Was ist mit der Verzögerung einer HTTP-Anfrage beim Schreiben in eine Suchleiste? Filtern von Ergebnissen während der Eingabe? Eine Sekunde zu warten, bevor eine gefilterte Liste angefordert wird, anstatt den Server nach jeder Taste abzufragen, die der Benutzer antippt, klingt für mich nicht nach Unsinn. –

17

Diese Zeile ruft die Wähler secondMethod nach 3 Sekunden:

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ]; 

Verwenden Sie es auf Ihrer zweite Operation mit Ihrer gewünschten Verzögerung. Wenn Sie viel Code haben, legen Sie ihn in eine eigene Methode und rufen Sie diese Methode mit performSelector:. Es wird nicht der UI-Block wie sleep

Edit: Wenn Sie Sie eine Kategorie hinzufügen könnte nicht ein zweites Verfahren wollen in der Lage sein, Blöcke zu verwenden, mit perform:

@implementation NSObject (PerformBlockAfterDelay) 

- (void)performBlock:(void (^)(void))block 
      afterDelay:(NSTimeInterval)delay 
{ 
    block = [block copy]; 
    [self performSelector:@selector(fireBlockAfterDelay:) 
       withObject:block 
       afterDelay:delay]; 
} 

- (void)fireBlockAfterDelay:(void (^)(void))block 
{ 
    block(); 
} 

@end 

Oder vielleicht noch sauberer:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void)) 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay), 
     dispatch_get_current_queue(), block); 
} 
+6

Die OP ausdrücklich erklärt sie nicht ein zweites Verfahren will: S –

+0

Er konnte eine Kategorie hinzufügen zu können, Blöcke verwenden, um mit 'performSelector': http://stackoverflow.com/questions/4007023/blocks-instead -of-performselectorwithobject nachherdelay – Sunkas

+0

@Sunkas: Danke für die Antwort. Aber ich habe bereits erwähnt, dass ich keine zweite Funktion hinzufügen möchte. –

2

Wenn Sie iOS Targeting sind komplizieren können Sie Folgendes tun können:

[executing first operation]; 
double delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [executing second operation]; 
}); 
+1

Sie meinen iOS 4? [Wichtige zentrale Aufgabe Funktionsreferenz] (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW3) –

23

können Sie die NSThread Methode verwenden:

[NSThread sleepForTimeInterval: delay]; 

wenn Sie jedoch tun dies auf dem Haupt-Thread Sie die App blockiert werden, so dass nur diesen Thread auf einem Hintergrund tun.


oder in Swift

NSThread.sleepForTimeInterval(delay) 

in Swift 3

Thread.sleep(forTimeInterval: delay) 
+0

Ich glaube, das sollte die akzeptierte Antwort gemäß den Anforderungen der Frage gewesen sein. – ACLima

+1

@ACLima: Entschuldigung, 'sleepForTimeInterval' wird den Thread für ein bestimmtes Zeitintervall abschalten, was Auswirkungen auf die Ausführung anderer gleichzeitiger Funktionen haben kann. –

+0

@KrishnaRajSalim ich sehe, danke – ACLima

8

Ich habe ein paar von Turn-basierten Spielen, wo ich die KI muß seine pausieren vor der Einnahme drehen (und zwischen den Schritten seinerseits). Ich bin mir sicher, dass es andere, nützlichere Situationen gibt, in denen eine Verzögerung die beste Lösung ist. In Swift:

 let delay = 2.0 * Double(NSEC_PER_SEC) 
     let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
     dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) } 

Ich bin gerade hier, um zu sehen, ob die Objective-C Anrufe unterschiedlich waren (ich dies, dass man hinzufügen müssen, auch..)

0

Wie @Sunkas schrieb, performSelector:withObject:afterDelay: ist der Anhänger der dispatch_after nur, dass es kürzer ist und Sie die normale objective-c Syntax haben. Wenn Sie Argumente an den Block übergeben müssen Sie verzögern wollen, können Sie sie einfach durch den Parameter übergeben withObject und Sie werden es in den Empfangs selector Sie rufen:

[self performSelector:@selector(testStringMethod:) 
      withObject:@"Test Test" 
      afterDelay:0.5]; 

- (void)testStringMethod:(NSString *)string{ 
    NSLog(@"string >>> %@", string); 
} 

Wenn Sie noch selbst wählen möchten, wenn Sie Führen Sie es im Hauptthread oder im aktuellen Thread aus. Es gibt bestimmte Methoden, mit denen Sie dies festlegen können. Apples Dokumentation erzählt dies:

Wenn Sie die Nachricht aus der Warteschlange entfernt werden soll, wenn die Laufschleife in einem Modus anders als der Standardmodus ist, verwenden Sie die perform: withobject: afterDelay: inModes: Methode statt. Wenn Sie nicht sicher sind, ob der aktuelle Thread der Haupt-Thread ist, können Sie die performSelectorOnMainThread verwenden: withobject: waitUntilDone: oder performSelectorOnMainThread: withobject: waitUntilDone: Modi: Methode Garantie, dass Ihr Selektor auf der Haupt-Thread ausgeführt wird. Um eine in die Warteschlange gestellte Nachricht abzubrechen, verwenden Sie die Methode cancelPreviousPerformRequestsWithTarget: oder cancelPreviousPerformRequestsWithTarget: selector: object: method.