web-dev-qa-db-fra.com

Ajout de délai entre l'exécution des deux lignes suivantes

Je dois ajouter un délai entre l'exécution de deux lignes dans la fonction a(same). Existe-t-il des options favorables pour ce faire?

Note: Je n'ai pas besoin de deux fonctions différentes pour le faire, et le délai ne doit pas affecter l'exécution des autres fonctions.

par exemple:

line 1: [executing first operation];

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

line 3: [executing second operation];

Toute aide est appréciable. Merci d'avance...

69
Krishna Raj Salim

Vous pouvez utiliser gcd pour cela sans avoir à créer une autre méthode

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

Vous devriez quand même vous demander "ai-je vraiment besoin d'ajouter un délai", car cela peut souvent compliquer le code et provoquer des conditions de concurrence

187
Paul.s

Vous pouvez utiliser la méthode NSThread:

[NSThread sleepForTimeInterval: delay];

Toutefois, si vous le faites sur le fil principal, vous bloquez l'application. Ne le faites donc que sur un fil d'arrière-plan.


ou en Swift

NSThread.sleepForTimeInterval(delay)

in Swift

Thread.sleep(forTimeInterval: delay)
26
Ashley Mills

Cette ligne appelle le sélecteur secondMethod après 3 secondes:

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

Utilisez-le sur votre deuxième opération avec le délai souhaité. Si vous avez beaucoup de code, placez-le dans sa propre méthode et appelez cette méthode avec performSelector:. Il ne bloquera pas l'interface utilisateur comme sleep

Edit: Si vous ne voulez pas d'une deuxième méthode, vous pouvez ajouter une catégorie pour pouvoir utiliser des blocs avec 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

Ou peut-être même plus propre:

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

J'ai quelques jeux au tour pour lesquels j'ai besoin de l'IA de faire une pause avant de prendre son tour (et entre les étapes à son tour). Je suis sûr qu'il existe d'autres situations, plus utiles, dans lesquelles un délai est la meilleure solution. En rapide:

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

Je suis juste revenu ici pour voir si les appels d'Objective-C étaient différents (je dois aussi ajouter ceci à celui-là).

8
David Reich

Si vous ciblez iOS 4.0+, vous pouvez effectuer les opérations suivantes:

[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];
});
3
Attila H

Comme @Sunkas l'a écrit, performSelector:withObject:afterDelay: est le pendentif du dispatch_after juste que c'est plus court et que vous avez la normale objective-c syntaxe. Si vous devez passer des arguments au bloc que vous souhaitez retarder, vous pouvez simplement les transmettre via le paramètre withObject et vous le recevrez dans le selector que vous appelez:

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

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

Si vous voulez toujours choisir vous-même si vous l'exécutez sur le thread principal ou sur le thread actuel, il existe des méthodes spécifiques qui vous permettent de spécifier cela. Apple Documentation indique ceci:

Si vous souhaitez que le message soit retiré de la file d'attente lorsque la boucle d'exécution est dans un mode autre que le mode par défaut, utilisez plutôt la méthode performSelector: withObject: afterDelay: inModes:. Si vous ne savez pas si le thread actuel est le thread principal, vous pouvez utiliser la méthode performSelectorOnMainThread: withObject: waitUntilDone: ou performSelectorOnMainThread: withObject: waitUntilDone: modes: pour garantir que votre sélecteur s'exécutera sur le thread principal. Pour annuler un message en file d'attente, utilisez cancelPreviousPerformRequestsWithTarget: ou cancelPreviousPerformRequestsWithTarget: selector: object: method.

0
Alex Cio