Je veux souvent exécuter du code quelques microsecondes à l'avenir. En ce moment, je le résous comme ceci:
- (void)someMethod
{
// some code
}
Et ça:
[self performSelector:@selector(someMethod) withObject:nil afterDelay:0.1];
Cela fonctionne, mais je dois créer une nouvelle méthode à chaque fois. Est-il possible d'utiliser des blocs à la place de cela? Fondamentalement, je recherche une méthode comme:
[self performBlock:^{
// some code
} afterDelay:0.1];
Ce serait vraiment utile pour moi.
Il n'y a pas de moyen intégré de le faire, mais ce n'est pas trop mal d'ajouter via une catégorie:
@implementation NSObject (PerformBlockAfterDelay)
- (void)performBlock:(void (^)(void))block
afterDelay:(NSTimeInterval)delay
{
block = [[block copy] autorelease];
[self performSelector:@selector(fireBlockAfterDelay:)
withObject:block
afterDelay:delay];
}
- (void)fireBlockAfterDelay:(void (^)(void))block {
block();
}
@end
Nous remercions Mike Ash pour l'implémentation de base.
Voici une technique simple, basée sur GCD, que j'utilise:
void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
dispatch_get_current_queue(), block);
}
Je ne suis pas un expert GCD, et je serais intéressé par des commentaires sur cette solution.
Une autre façon (peut-être la pire façon de le faire pour de nombreuses raisons) est:
[UIView animateWithDuration:0.0 delay:5.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
} completion:^(BOOL finished) {
//do stuff here
}];
Si vous avez spécifiquement besoin d'un délai plus long, les solutions ci-dessus fonctionnent très bien. J'ai utilisé l'approche de @ nick avec beaucoup de succès.
Cependant, si vous voulez simplement que votre bloc s'exécute lors de la prochaine itération de la boucle principale, vous pouvez le réduire encore plus avec juste ce qui suit:
[[NSOperationQueue mainQueue] addOperationWithBlock:aBlock];
Cela revient à utiliser performSelector: avec afterDelay de 0.0f
J'ai utilisé un code similaire comme celui-ci:
double delayInSeconds = 0.2f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//whatever you wanted to do here...
});
Il y a une catégorie Nice, complète qui gère cette situation ici: