2013-03-11 8 views
57

È necessario aggiungere un ritardo tra l'esecuzione di due righe in una (stessa) funzione. C'è qualche opzione favorevole per fare questo?Aggiunta di ritardo tra l'esecuzione di due righe successive

Nota: Non sono necessarie due funzioni diverse per eseguire questa operazione e il ritardo non deve influire sull'esecuzione di altre funzioni.

esempio:

line 1: [executing first operation]; 

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

line 3: [executing second operation]; 

Ogni aiuto è apprezzabile. Grazie in anticipo ...

risposta

149

È possibile utilizzare GCD per fare questo senza dover creare un altro metodo

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"); 
}); 

Si dovrebbe comunque chiedere a te stesso "Ho davvero bisogno di aggiungere un ritardo", come spesso può complicare il codice e causare condizioni di gara

+2

È corretto avvisare la gente di questo, ma se si codificano i controller che devono attendere un dispositivo esterno con un tempo di elaborazione fisso NON è un senso. – user2161301

+2

Che dire del ritardo di una richiesta HTTP durante la scrittura in una barra di ricerca? Filtrare i risultati durante la digitazione? Aspettando un secondo prima di richiedere un elenco filtrato invece di interrogare il server per ogni chiave che l'utente tocca, non mi sembra un'assurdità. –

17

Questa linea chiama il selettore secondMethod dopo 3 secondi:

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

utilizzare sul vostro seconda operazione con il ritardo desiderato. Se disponi di un sacco di codice, inseriscilo nel suo metodo e chiama questo metodo con performSelector:. E 'abitudine bloccare l'interfaccia utente come sleep

Edit: Se non si desidera un secondo metodo si potrebbe aggiungere una categoria per essere in grado di utilizzare blocchi con performSelector:

@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 

O forse ancora più pulito:

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

Il PO afferma esplicitamente che non vogliono un secondo metodo: S –

+0

Si potrebbe aggiungere una categoria per essere in grado di utilizzare blocchi con 'performSelector': http://stackoverflow.com/questions/4007023/blocks-instead -di-performselectorwithobjectafterdelay – Sunkas

+0

@Sunkas: Grazie per la risposta. Ma ho già detto che non voglio aggiungere una seconda funzione. –

2

Se sei targeting iOS 4.0+, è possibile effettuare le seguenti operazioni:

[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

Intendi iOS 4? [Riferimento funzione Grand central dispatch] (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW3) –

23

È possibile utilizzare il metodo NSThread:

[NSThread sleepForTimeInterval: delay]; 

Tuttavia, se si esegue questa operazione sul thread principale si blocca l'applicazione, in modo da farlo solo su un thread in background.


o in Swift

NSThread.sleepForTimeInterval(delay) 

a Swift 3

Thread.sleep(forTimeInterval: delay) 
+0

Credo che questa dovrebbe essere la risposta accettata in base ai requisiti della domanda. – ACLima

+1

@ACLima: Spiacenti, 'sleepForTimeInterval' ospiterà il thread per un dato intervallo di tempo, che potrebbe influire sull'esecuzione di altre funzioni simultanee. –

+0

@KrishnaRajSalim vedo, grazie – ACLima

8

Ho un paio di giochi a turni in cui ho bisogno l'IA per mettere in pausa prima di prendere la sua girare (e tra i passaggi a sua volta). Sono sicuro che ci sono altre, più utili, situazioni in cui un ritardo è la soluzione migliore. 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) } 

Sono appena tornato qui per vedere se le chiamate Objective-C erano diversi (ho bisogno di aggiungere questo a quello, anche..

0

Come @Sunkas ha scritto, performSelector:withObject:afterDelay: è il pendente per lo dispatch_after solo che è più corto e si ha la normale sintassi objective-c. Se avete bisogno di passare gli argomenti al blocco che si desidera ritardare, si può semplicemente passare attraverso il parametro withObject e riceverai nella selector si chiama:

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

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

Se si vuole ancora di scegliere da soli se si eseguirlo sul thread principale o sul thread corrente, ci sono metodi specifici che ti permettono di specificarlo. Le mele Documentazione dice questo:

Se si desidera che il messaggio venga eliminato dalla coda quando il ciclo di esecuzione è in una modalità diversa da la modalità predefinita, utilizzare il performSelector: withObject: afterDelay: inModes: invece il metodo. Se non si è sicuri se il thread corrente è il filo conduttore, è possibile utilizzare il performSelectorOnMainThread: withObject: waitUntilDone: o performSelectorOnMainThread: withObject: waitUntilDone: modalità: metodo per garanzia che il vostro selettore eseguito sul thread principale. Per annullare un messaggio in coda , utilizzare cancelPreviousPerformRequestsWithTarget o cancelPreviousPerformRequestsWithTarget: selector: object: method.

Problemi correlati