Vous savez très certainement différer l’invocation d’un sélecteur (méthode d’un objet Objective C) en utilisant les méthodes dédiées de NSObject. performSelector:withObject:afterDelay
Par exemple :
1 | [self performSelector:@selector(display:) withObject:myChain afterDelay:1]; |
“performSelector:withObject:afterDelay” ne peut pas invoquer :
- Une méthode comportant un type différent de NSObject. (Ligne 1 du code ci-dessous)
- Une méthode comportant plusieurs argument (Lignes 2 à 3)
1 2 3 | -(void)doSomethingWithBool:(BOOL)shouldDoThat; -(void)doSomethingWithFirstArgument:(NSString*)firstString andSecondArgument:(NSString*)secondString; |
Il conviendrait de pouvoir différer l’exécution d’un bloc de code arbitraire, comportant un ou des appels différés. Comment différer l’exécution d’un bloc ?
Solution :
Nous allons utiliser Grand Central Dispatch (GCD) pour différer l’exécution d’un bloc. (cette solution est compatible avec IOS 4.x et plus)
1 2 3 4 5 6 7 | int delay=1; // Délai en secondes dispatch_after( dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ // Le "bloc" à exécuter [self doSomethingWithBool:NO]; [self doSomethingWithFirstArgument:@"one" andSecondArgument:@"two"]; }); |
Création d’une méthode générique pour différer l’exécution d’un bloc :
1 2 3 4 | - (void)performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay { dispatch_after( dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_current_queue(),block); } |
Exemple d’invocation :
1 2 3 | [self performBlock:^{ [self doSomethingWithFirstArgument:@"one" andSecondArgument:@"two"]; } afterDelay:0]; |
Que se passe-t’il si nous nous utilisons un délai == 0 ?
Le code est exécuté immédiatement à la fin de la pile d’exécution (“run loop”)
Vous pouvez si vous le souhaitez créer une catégorie NSObject+Blocks pour intégrer cette méthode au comportement standard des NSObject. Pour ma part je préfère utiliser un singleton utilitaire pour ce type de tâche.