Je veux suspendre mon application à un certain point. En d'autres termes, je veux que mon application exécute le code, mais à un certain moment, faites une pause de 4 secondes, puis continuez avec le reste du code. Comment puis-je faire ceci?
J'utilise Swift.
Réponses:
Au lieu d'un sommeil, qui verrouillera votre programme s'il est appelé à partir du thread d'interface utilisateur, envisagez d'utiliser
NSTimer
ou un temporisateur de répartition.Mais, si vous avez vraiment besoin d'un délai dans le thread actuel:
Cela utilise la
sleep
fonction d'UNIX.la source
Dans la
dispatch_after
plupart des cas, l' utilisation d'un bloc est préférable à l'utilisation,sleep(time)
car le thread sur lequel le sommeil est effectué est empêché d'effectuer d'autres travaux. lorsque vous utilisezdispatch_after
le thread sur lequel vous travaillez, il n'est pas bloqué, il peut donc effectuer d'autres tâches en attendant.Si vous travaillez sur le thread principal de votre application, l'utilisation
sleep(time)
est mauvaise pour l'expérience utilisateur de votre application car l'interface utilisateur ne répond pas pendant ce temps.Dispatch after planifie l'exécution d'un bloc de code au lieu de geler le thread:
Swift ≥ 3,0
Rapide <3,0
la source
.now() + .seconds(4)
Donne précédemment une erreur:expression type is ambiguous without more context
.now() + .seconds(5)
c'est tout simplement.now() + 5
Comparaison entre différentes approches dans swift 3.0
1. Dormir
Cette méthode n'a pas de rappel. Mettez les codes directement après cette ligne pour les exécuter en 4 secondes. Il empêchera l'utilisateur d'itérer avec des éléments d'interface utilisateur comme le bouton de test jusqu'à ce que le temps soit écoulé. Bien que le bouton soit gelé lorsque le sommeil entre en action, d'autres éléments comme l'indicateur d'activité tournent toujours sans geler. Vous ne pouvez plus déclencher cette action pendant le sommeil.
2. Envoi, exécution et minuterie
Ces trois méthodes fonctionnent de manière similaire, elles s'exécutent toutes sur le thread d'arrière-plan avec des rappels, juste avec une syntaxe différente et des fonctionnalités légèrement différentes.
La répartition est couramment utilisée pour exécuter quelque chose sur le thread d'arrière-plan. Il a le rappel dans le cadre de l'appel de fonction
Perform est en fait une minuterie simplifiée. Il met en place une minuterie avec le retard, puis déclenche la fonction par sélecteur.
Et enfin, le minuteur permet également de répéter le rappel, ce qui n'est pas utile dans ce cas
Pour ces trois méthodes, lorsque vous cliquez sur le bouton pour les déclencher, l'interface utilisateur ne se fige pas et vous êtes autorisé à cliquer à nouveau dessus. Si vous cliquez à nouveau sur le bouton, une autre minuterie est configurée et le rappel sera déclenché deux fois.
En conclusion
Aucune des quatre méthodes ne fonctionne assez bien seule.
sleep
désactivera l'interaction avec l'utilisateur, de sorte que l'écran "se fige " (pas réellement) et entraîne une mauvaise expérience utilisateur. Les trois autres méthodes ne gèleront pas l'écran, mais vous pouvez les déclencher plusieurs fois, et la plupart du temps, vous voulez attendre que vous récupériez l'appel avant de permettre à l'utilisateur de refaire l'appel.Ainsi, une meilleure conception utilisera l'une des trois méthodes asynchrones avec blocage d'écran. Lorsque l'utilisateur clique sur le bouton, couvrez tout l'écran avec une vue translucide avec un indicateur d'activité de rotation sur le dessus, indiquant à l'utilisateur que le clic sur le bouton est en cours de traitement. Ensuite, supprimez la vue et l'indicateur dans la fonction de rappel, indiquant à l'utilisateur que l'action est correctement gérée, etc.
la source
@objc
devant la fonction de rappel pour l'perform(...)
option. Comme ça:@objc func callback() {
Je suis d'accord avec Palle que l'utilisation
dispatch_after
est un bon choix ici. Mais vous n'aimez probablement pas les appels GCD car ils sont assez ennuyeux à écrire . Au lieu de cela, vous pouvez ajouter cette aide pratique :Maintenant, vous retardez simplement votre code sur un fil d'arrière-plan comme celui-ci:
Retarder le code sur le thread principal est encore plus simple:
Si vous préférez un Framework qui possède également des fonctionnalités plus pratiques, passez à HandySwift . Vous pouvez l'ajouter à votre projet via Carthage ou Accio puis l'utiliser exactement comme dans les exemples ci-dessus:
la source
DispatchTime
n'était pas disponible dans Swift 2. C'étaitlet dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
avant.Vous pouvez également le faire avec Swift 3.
Exécutez la fonction après un délai comme ceci.
la source
Dans Swift 4.2 et Xcode 10.1
Vous avez au total 4 façons de retarder. Parmi ces options, il est préférable d'appeler ou d'exécuter une fonction après un certain temps. Le sleep () est le moins utilisé.
Option 1.
Option 2.
Option 3.
Option 4.
Si vous voulez appeler une fonction après un certain temps pour exécuter quelque chose, n'utilisez pas sleep .
la source
NSTimer
La réponse de @nneonneo a suggéré d'utiliser
NSTimer
mais n'a pas montré comment le faire. Voici la syntaxe de base:Voici un projet très simple pour montrer comment il pourrait être utilisé. Lorsqu'une touche est enfoncée, elle démarre une minuterie qui appelle une fonction après un délai d'une demi-seconde.
L'utilisation
dispatch_time
(comme dans la réponse de Palle ) est une autre option valable. Cependant, il est difficile d'annuler . AvecNSTimer
, pour annuler un événement différé avant qu'il ne se produise, il vous suffit d'appelerL'utilisation
sleep
n'est pas recommandée, en particulier sur le thread principal, car elle empêche tout travail en cours sur le thread.Voir ici pour ma réponse plus complète.
la source
Essayez l'implémentation suivante dans Swift 3.0
Usage
la source
Vous pouvez créer une extension pour utiliser facilement la fonction de retard (Syntaxe: Swift 4.2+)
Comment utiliser dans UIViewController
la source
Si vous devez définir un délai inférieur à une seconde, il n'est pas nécessaire de définir le paramètre .seconds. J'espère que cela est utile à quelqu'un.
la source
la source
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {/*Do stuff*/}
est probablement plus correct ✌️Si votre code s'exécute déjà dans un thread d'arrière-plan, mettez le thread en pause à l'aide de cette méthode dans Foundation :
Thread.sleep(forTimeInterval:)
Par exemple:
(Voir d'autres réponses pour des suggestions lorsque votre code s'exécute sur le thread principal.)
la source
Pour créer un délai simple, vous pouvez importer Darwin, puis utiliser la mise en veille (secondes) pour effectuer le délai. Cela ne prend que des secondes entières, cependant, pour des mesures plus précises, vous pouvez importer Darwin et utiliser l'usep (millionièmes de seconde) pour une mesure très précise. Pour tester cela, j'ai écrit:
Qui imprime, puis attend 1 seconde et imprime, puis attend 0,4 seconde puis imprime. Tout a fonctionné comme prévu.
la source
c'est le plus simple
la source