perform pause code after xcode swift delay

xcode - code - swift pause time



¿Cómo crear un retraso en Swift? (10)

Quiero detener mi aplicación en cierto punto. En otras palabras, quiero que mi aplicación ejecute el código, pero luego, en cierto punto, pausa durante 4 segundos y luego continúa con el resto del código. ¿Cómo puedo hacer esto?

Estoy usando Swift.


NSTimer

La respuesta de @nneonneo sugirió usar NSTimer pero no mostró cómo hacerlo. Esta es la sintaxis básica:

let delay = 0.5 // time in seconds NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(myFunctionName), userInfo: nil, repeats: false)

Aquí hay un proyecto muy simple para mostrar cómo se podría usar. Cuando se presiona un botón, se inicia un temporizador que llamará a una función después de un retraso de medio segundo.

import UIKit class ViewController: UIViewController { var timer = NSTimer() let delay = 0.5 // start timer when button is tapped @IBAction func startTimerButtonTapped(sender: UIButton) { // cancel the timer in case the button is tapped multiple times timer.invalidate() // start the timer timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) } // function to be called after the delay func delayedAction() { print("action has started") } }

Usar dispatch_time (como en la respuesta de Palle ) es otra opción válida. Sin embargo, es difícil de cancelar . Con NSTimer , para cancelar un evento retrasado antes de que suceda, todo lo que necesita hacer es llamar

timer.invalidate()

No se recomienda utilizar sleep , especialmente en el hilo principal, ya que detiene todo el trabajo realizado en el hilo.

Vea here mi respuesta más completa.


Estoy de acuerdo con Palle en que usar dispatch_after es una buena opción aquí. Pero probablemente no te gusten las llamadas GCD ya que son bastante molestas de escribir . En su lugar, puede agregar este práctico ayudante :

public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) { let dispatchTime = DispatchTime.now() + seconds dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure) } public enum DispatchLevel { case main, userInteractive, userInitiated, utility, background var dispatchQueue: DispatchQueue { switch self { case .main: return DispatchQueue.main case .userInteractive: return DispatchQueue.global(qos: .userInteractive) case .userInitiated: return DispatchQueue.global(qos: .userInitiated) case .utility: return DispatchQueue.global(qos: .utility) case .background: return DispatchQueue.global(qos: .background) } } }

Ahora simplemente demoras tu código en un hilo de fondo como este:

delay(bySeconds: 1.5, dispatchLevel: .background) { // delayed code that will run on background thread }

Retraso de código en el hilo principal es aún más simple:

delay(bySeconds: 1.5) { // delayed code, by default run in main thread }

Si prefiere un Framework que también tenga algunas características más útiles, HandySwift compra de HandySwift . Puede agregarlo a su proyecto a través de Cartago y luego usarlo exactamente como en los ejemplos anteriores:

import HandySwift delay(by: .seconds(1.5)) { // delayed code }


Para crear un retraso de tiempo simple, puede importar Darwin y luego usar sleep (segundos) para realizar el retraso. Sin embargo, eso solo requiere segundos enteros, por lo que para mediciones más precisas puede importar Darwin y usar el modo sleep (millonésimas de segundo) para realizar mediciones muy precisas. Para probar esto, escribí:

import Darwin print("This is one.") sleep(1) print("This is two.") usleep(400000) print("This is three.")

Que imprime, luego espera 1 segundo e imprime, luego espera 0.4 segundos y luego imprime. Todo funcionó como se esperaba.


Pruebe la siguiente implementación en Swift 3.0

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

Uso

delayWithSeconds(1) { //Do something }


También puedes hacer esto con Swift 3.

Realice la función después de la demora como ese.

override func viewDidLoad() { super.viewDidLoad() self.perform(#selector(ClassName.performAction), with: nil, afterDelay: 2.0) } @objc func performAction() { //This function will perform after 2 seconds print("Delayed") }


Usar un bloque dispatch_after es en la mayoría de los casos mejor que usar sleep(time) ya que el hilo en el que se realiza el sueño está bloqueado para realizar otro trabajo. cuando se utiliza dispatch_after el hilo en el que se trabaja no se bloquea, por lo que puede hacer otros trabajos mientras tanto.
Si está trabajando en el hilo principal de su aplicación, el uso de sleep(time) es malo para la experiencia del usuario de su aplicación, ya que la interfaz de usuario no responde durante ese tiempo.

Despachar después de los horarios la ejecución de un bloque de código en lugar de congelar el hilo:

Swift ≥ 3.0

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: { // Put your code which should be executed with a delay here })

Swift <3.0

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 }


este es el más simple

delay(0.3, closure: { // put her any code you want to fire it with delay button.removeFromSuperview() })


Comparación entre diferentes enfoques en swift 3.0

1. Dormir

Este método no tiene una devolución de llamada. Coloque los códigos directamente después de esta línea para que se ejecuten en 4 segundos. Se detendrá al usuario de iterar con elementos de la interfaz de usuario como el botón de prueba hasta que se acabe el tiempo. Aunque el botón se congela cuando suena el sueño, otros elementos, como el indicador de actividad, siguen girando sin congelarse. No puede disparar esta acción nuevamente durante el descanso.

sleep(4) print("done")//Do stuff here

2. Despacho, ejecución y temporizador

Estos tres métodos funcionan de manera similar, todos se ejecutan en el hilo de fondo con devolución de llamadas, solo con una sintaxis diferente y características ligeramente diferentes.

El envío se usa comúnmente para ejecutar algo en el hilo de fondo. Tiene la devolución de llamada como parte de la llamada de función

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: { print("done") })

Realizar es en realidad un temporizador simplificado. Configura un temporizador con la demora y luego activa la función por selector.

perform(#selector(callback), with: nil, afterDelay: 4.0) func callback() { print("done") }}

Y finalmente, el temporizador también proporciona la capacidad de repetir la devolución de llamada, lo que no es útil en este caso

Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(callback), userInfo: nil, repeats: false) func callback() { print("done") }}

Para todos estos tres métodos, al hacer clic en el botón para activarlos, la IU no se congelará y podrá hacer clic de nuevo. Si vuelve a hacer clic en el botón, se configura otro temporizador y la devolución de llamada se activará dos veces.

En conclusión

Ninguno de los cuatro métodos funciona lo suficientemente bien solo. sleep inhabilitará la interacción del usuario, por lo que la pantalla se " congela " (no en realidad) y los resultados son una mala experiencia para el usuario. Los otros tres métodos no congelarán la pantalla, pero puede activarlos varias veces, y la mayoría de las veces, desea esperar hasta que reciba la devolución de llamada antes de permitir que el usuario realice la llamada nuevamente.

Entonces, un diseño mejor utilizará uno de los tres métodos asíncronos con bloqueo de pantalla. Cuando el usuario hace clic en el botón, cubre toda la pantalla con una vista translúcida con un indicador de actividad giratoria en la parte superior, indicándole al usuario que se está manejando el clic del botón. Luego, elimine la vista y el indicador en la función de devolución de llamada, indicándole al usuario que la acción se manejó adecuadamente, etc.


En lugar de un reposo, que bloqueará su programa si se llama desde el subproceso de interfaz de usuario, considere usar NSTimer o un temporizador de despacho.

Pero, si realmente necesita un retraso en el hilo actual:

... { sleep(4) }

Esto usa la función sleep de UNIX.


var bg:DispatchQueue = {return DispatchQueue.global(qos: DispatchQoS.QoSClass.background)}()//keep this in the global scope bg.async { sleep(4) print("Active after 4 sec, and doesn''t block main") }