Come programmare un ritardo in Swift 3


330

Nelle versioni precedenti di Swift, si poteva creare un ritardo con il seguente codice:

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
}

Ma ora, in Swift 3, Xcode cambia automaticamente 6 cose diverse ma poi appare il seguente errore: "Impossibile convertire DispatchTime.nowal valore atteso dispatch_time_taka UInt64".

Come si può creare un ritardo prima di eseguire una sequenza di codice in Swift 3?

Risposte:


967

Dopo molte ricerche, ho finalmente capito questo.

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

Questo crea l'effetto "attesa" desiderato in Swift 3 e Swift 4.

Ispirato da una parte di questa risposta .


7
Contributo utile, grazie! Aggiornamento per Swift 3 più recente:DispatchQueue.main.asyncAfter(deadline: when)
Rogare

77
Potresti rendere il tuo codice un po 'più veloce sostituendo "+ 2" con "+ .seconds (2)". Oppure, per il massimo della velocità, puoi eliminare la prima riga e sostituire "deadline: when" con "deadline: .now () + .seconds (2)".
RenniePet

2
@ OctavioAntonioCedeño Felice di aiutarti. Questo mi ha davvero infastidito per un po ': D
owlswipe il

5
Funziona ancora il 3/12/2017. Grazie mille per questo :)
John Leonardo

3
Letteralmente il mio post più visitato su SO. È più facile trovare questo post piuttosto che ricordarlo o trovarlo altrove nel mio codice;)
barrylachapelle

154

Mi piace la notazione a riga singola per GCD, è più elegante:

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

Inoltre, in iOS 10 abbiamo nuovi metodi Timer, ad esempio inizializzazione a blocchi:

(quindi l'azione ritardata può essere annullata)

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

A proposito, tieni presente: per impostazione predefinita, il timer viene aggiunto alla modalità di esecuzione del ciclo predefinita. Significa che il timer può essere bloccato quando l'utente interagisce con l'interfaccia utente dell'app (ad esempio, durante lo scorrimento di un UIScrollView) È possibile risolvere questo problema aggiungendo il timer alla modalità di esecuzione del ciclo specifica:

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

In questo post di blog puoi trovare maggiori dettagli.


4
Buona pesca! Non l'avevo ancora visto.
julien_c,

8
più uno per il confronto Timer e la dichiarazione di non responsabilità sul runloop principale!
Martin

2
Bella presa! Questo è ingegneria.
Onur hindahindur,

56

Prova la seguente funzione implementata in Swift 3.0 e versioni successive

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

uso

delayWithSeconds(1) {
   //Do something
}

5
Fondamentalmente hai appena copiato questa risposta, ma sì, va bene, grazie.
gufowipe

2
Come annullare questo?
Sourav Chandra,

24

Prova il codice qui sotto per il ritardo

//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
I display del primo modo hanno l'errore "Uso dell'identificatore non risolto 'ritardo'"
Jerry Chong

5
Questo programmatore sta lavorando con un metodo di supporto nella sua base di codice e lo ha da molto tempo. Quindi il ritardo era il codice che ha usato per un po 'non sapendo che non è a parte l'SDK di Apple.
Nick Perkins,

4

Un modo è usare DispatchQueue.main.asyncAftercome molte persone hanno risposto.

Un altro modo è quello di usare perform(_:with:afterDelay:). Maggiori dettagli qui

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

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

1

// Esegue la funzione dopo x secondi

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)
}

//Uso:-

runThisAfterDelay(seconds: x){
  //write your code here
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.