32 votes

Comment fonctionne -performSelector: withObject: afterDelay:?

Je travaille actuellement dans l'hypothèse que -performSelector:withObject:afterDelay: n'utilise pas de thread, mais planifie un événement pour qu'il se déclenche à une date ultérieure sur le thread actuel. Est-ce correct?

Plus précisement:

 - (void) methodCalledByButtonClick {
  for (id obj in array) {
    [self doSomethingWithObj:obj];
  }
}

static BOOL isBad = NO;
- (void) doSomethingWithObj:(id)obj {
  if (isBad) {
    return;
  }
  if ([obj isBad]) {
    isBad = YES;
    [self performSelector:@selector(resetIsBad) withObject:nil afterDelay:0.1];
    return;
  }
  //Do something with obj
}

- (void) resetIsBad {
  isBad = NO;
}
 

Est-il garanti que -resetIsBad ne sera pas appelé avant le retour de -methodCalledByButtonClick , en supposant que nous fonctionnons sur le thread principal, même si -methodCalledByButtonClick prend un temps arbitrairement long pour Achevée?

45voto

Benoit Points 39210

À partir de la docs:

Invoque une méthode du récepteur sur la le thread en cours à l'aide de la valeur par défaut mode après un certain délai.

Le débat va plus loin:

Cette méthode permet de définir une minuterie pour effectuer le aSelector message sur le courant la course du fil de la boucle. La minuterie est configuré pour s'exécuter dans le mode par défaut (NSDefaultRunLoopMode). Lorsque la minuterie les incendies, le thread tente de file d'attente le message de l'exécution de la boucle et effectuer la sélection. Il réussit si l'exécution de la boucle est en cours d'exécution et dans le le mode par défaut; sinon, la minuterie attend jusqu'à ce que l'exécution de la boucle est dans le le mode par défaut.

De cela, nous pouvons répondre à votre deuxième question. Oui, c'est garanti, même avec un délai plus court depuis le thread courant est occupé à exécuter lors de l' performSelector est appelé. Lorsque le thread retourne à l'exécution de la boucle et retire le sélecteur, vous aurez renvoyés à partir de votre methodCalledByButtonClick.

12voto

Asher Dunn Points 1702

performSelector:withObject:afterDelay: horaires d'une minuterie sur le même fil pour appeler le sélecteur d'après le passé délai. Si vous vous inscrivez à la valeur par défaut en mode run (c'est à dire ne pas utiliser performSelector:withObject:afterDelay:inModes:- )), je crois qu'il est garanti à attendre jusqu'à la prochaine passer à travers l'exécution de la boucle, donc tout sur la pile de terminer premier.

Même si vous appelez avec un retard de 0, il faudra patienter jusqu'à la prochaine boucle, et de se comporter comme vous le souhaitez ici. Pour plus d'informations, reportez-vous à la documentation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X