Cómo programar un retraso en Swift 3


330

En versiones anteriores de Swift, uno podría crear un retraso con el siguiente código:

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
    //put your code which should be executed with a delay here
}

Pero ahora, en Swift 3, Xcode cambia automáticamente 6 cosas diferentes, pero luego aparece el siguiente error: "No se puede convertir DispatchTime.nowal valor esperado dispatch_time_taka UInt64".

¿Cómo se puede crear un retraso antes de ejecutar una secuencia de código en Swift 3?

Respuestas:


967

Después de mucha investigación, finalmente descubrí esto.

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Change `2.0` to the desired number of seconds.
   // Code you want to be delayed
}

Esto crea el efecto de "espera" deseado en Swift 3 y Swift 4.

Inspirado por una parte de esta respuesta .


77
Contribución útil, gracias! Actualización para el Swift 3 más reciente:DispatchQueue.main.asyncAfter(deadline: when)
Rogare

77
Puede hacer que su código sea un poco más rápido reemplazando "+ 2" con "+ .seconds (2)". O, para lo último en rapidez, puede soltar la primera línea y reemplazar "fecha límite: cuando" con "fecha límite: .now () + .segundos (2)".
RenniePet

2
@ OctavioAntonioCedeño Feliz de ayudar. Esto realmente me molestó por un tiempo: D
owlswipe

55
Todavía trabajando 3/12/2017. Muchas gracias por esto :)
John Leonardo

3
Literalmente, mi publicación más visitada en SO. Es más fácil encontrar esta publicación que recordarla o encontrarla en otra parte de mi código;)
barrylachapelle

154

Me gusta la notación de una línea para GCD, es más elegante:

    DispatchQueue.main.asyncAfter(deadline: .now() + 42.0) {
        // do stuff 42 seconds later
    }

Además, en iOS 10 tenemos nuevos métodos de temporizador, por ejemplo, inicializador de bloque:

(por lo que se puede cancelar la acción retrasada)

    let timer = Timer.scheduledTimer(withTimeInterval: 42.0, repeats: false) { (timer) in
        // do stuff 42 seconds later
    }

Por cierto, tenga en cuenta: de manera predeterminada, el temporizador se agrega al modo de ciclo de ejecución predeterminado. Significa que el temporizador puede congelarse cuando el usuario interactúa con la interfaz de usuario de su aplicación (por ejemplo, al desplazarse por un UIScrollView). Puede resolver este problema agregando el temporizador al modo de ciclo de ejecución específico:

RunLoop.current.add(timer, forMode: .common)

En esta publicación de blog puedes encontrar más detalles.


44
¡Buena atrapada! No había visto esto todavía.
julien_c

8
¡más uno para la comparación de Timer y el descargo de responsabilidad sobre el runloop principal!
Martin

2
¡Buena atrapada! Esto es ingenieria.
Onur hindahindur

56

Pruebe la siguiente función implementada en Swift 3.0 y superior

func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { 
        completion()
    }
}

Uso

delayWithSeconds(1) {
   //Do something
}

55
Básicamente copiaste esta respuesta, pero sí, está bien, gracias.
owlswipe

2
¿Cómo cancelar esto?
Sourav Chandra

24

Pruebe el siguiente código para retrasos

//MARK: First Way

func delayForWork() {
    delay(3.0) {
        print("delay for 3.0 second")
    }
}

delayForWork()

// MARK: Second Way

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    // your code here delayed by 0.5 seconds
}

1
La primera pantalla muestra el error "Uso del identificador no resuelto 'retraso'"
Jerry Chong

55
Este programador está trabajando con un método auxiliar en su base de código y lo ha hecho durante mucho tiempo. Entonces, el retraso fue el código que ha usado durante un tiempo sin saber que no es parte del SDK de Apple.
Nick Perkins el

4

Una forma es usarlo DispatchQueue.main.asyncAftercomo mucha gente ha respondido.

Otra forma es usar perform(_:with:afterDelay:). Más detalles aquí

perform(#selector(delayedFunc), with: nil, afterDelay: 3)

@IBAction func delayedFunc() {
    // implement code
}

1

// Ejecuta la función después de x segundos

public static func runThisAfterDelay(seconds: Double, after: @escaping () -> Void) {
    runThisAfterDelay(seconds: seconds, queue: DispatchQueue.main, after: after)
}

public static func runThisAfterDelay(seconds: Double, queue: DispatchQueue, after: @escaping () -> Void) {
    let time = DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
    queue.asyncAfter(deadline: time, execute: after)
}

//Utilizar:-

runThisAfterDelay(seconds: x){
  //write your code here
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.