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?

búho
fuente

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 .

búho
fuente
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.

Victor Do
fuente
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
}
Vakas
fuente
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
}
Anand Verma
fuente
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
}
Zohaib Brohi
fuente
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
}
Pratyush Pratik
fuente