Cara memprogram penundaan di Swift 3

330

Di versi Swift sebelumnya, seseorang dapat membuat penundaan dengan kode berikut:

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
}

Tetapi sekarang, di Swift 3, Xcode secara otomatis mengubah 6 hal berbeda tetapi kemudian muncul kesalahan berikut: "Tidak dapat mengonversi DispatchTime.nowke nilai yang diharapkan dispatch_time_talias UInt64."

Bagaimana cara membuat penundaan sebelum menjalankan urutan kode di Swift 3?

owlswipe
sumber

Jawaban:

967

Setelah banyak penelitian, saya akhirnya menemukan yang ini.

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

Ini menciptakan efek "tunggu" yang diinginkan di Swift 3 dan Swift 4.

Terinspirasi oleh sebagian dari jawaban ini .

owlswipe
sumber
7
Kontribusi yang bermanfaat, terima kasih! Memperbarui untuk Swift 3 terbaru:DispatchQueue.main.asyncAfter(deadline: when)
Rogare
77
Anda bisa membuat kode Anda sedikit lebih cepat dengan mengganti "+ 2" dengan "+ .seconds (2)". Atau, untuk yang terbaik dalam kecepatan, Anda bisa menghilangkan baris pertama dan mengganti "batas waktu: ketika" dengan "batas waktu: .sekarang () + .detik (2)".
RenniePet
2
@ OctavioAntonioCedeño Senang membantu. Ini benar-benar menyadap saya untuk sementara waktu: D
owlswipe
5
Masih bekerja 3/12/2017. Terima kasih banyak atas ini :)
John Leonardo
3
Secara harfiah posting saya yang paling banyak dikunjungi di SO. Lebih mudah menemukan posting ini daripada benar-benar mengingatnya atau menemukannya di tempat lain dalam kode saya;)
barrylachapelle
154

Saya suka notasi satu baris untuk GCD, lebih elegan:

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

Juga, di iOS 10 kami memiliki metode Timer baru, mis. Blok inisialisasi:

(jadi tindakan yang tertunda dapat dibatalkan)

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

Btw, perlu diingat: secara default, timer ditambahkan ke mode run loop default. Ini berarti timer dapat dibekukan ketika pengguna berinteraksi dengan UI aplikasi Anda (misalnya, ketika menggulir UIScrollView) Anda dapat menyelesaikan masalah ini dengan menambahkan timer ke mode run loop spesifik:

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

Di posting blog ini Anda dapat menemukan lebih banyak detail.

Victor Do
sumber
4
Tangkapan yang bagus! Saya belum melihat ini.
julien_c
8
plus satu untuk perbandingan Timer dan penafian tentang runloop utama!
Martin
2
Tangkapan bagus! Ini rekayasa.
Onur Şahindur
56

Coba fungsi berikut diimplementasikan dalam Swift 3.0 dan di atas

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

Pemakaian

delayWithSeconds(1) {
   //Do something
}
Vaka
sumber
5
Anda pada dasarnya hanya menyalin jawaban ini tetapi ya ini bagus, terima kasih.
owlswipe
2
Bagaimana cara membatalkan ini?
Sourav Chandra
24

Coba kode di bawah ini untuk menunda

//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
sumber
1
Tampilan cara pertama memiliki kesalahan "Penggunaan 'keterlambatan' pengidentifikasi yang tidak terselesaikan"
Jerry Chong
5
Programmer ini bekerja dengan metode pembantu dalam basis kodenya dan sudah sejak lama. Jadi keterlambatan adalah kode yang dia gunakan untuk sementara waktu tidak tahu itu tidak terlepas dari SDK Apple.
Nick Perkins
4

Salah satu caranya adalah menggunakan DispatchQueue.main.asyncAfterkarena banyak orang telah menjawab.

Cara lain adalah menggunakan perform(_:with:afterDelay:). Lebih detail di sini

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

@IBAction func delayedFunc() {
    // implement code
}
Zohaib Brohi
sumber
1

// Menjalankan fungsi setelah x detik

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

//Menggunakan:-

runThisAfterDelay(seconds: x){
  //write your code here
}
Pratyush Pratik
sumber