Cara membuat antrian pengiriman di Swift 3

403

Di Swift 2, saya dapat membuat antrian dengan kode berikut:

let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT)

Tapi ini tidak dikompilasi di Swift 3.

Apa cara yang disukai untuk menulis ini di Swift 3?

Karthik Kumar
sumber
2
Kemungkinan rangkap
rickster
Swift 4 memiliki 3 params tambahan untuk membuat antrian serial. Bagaimana cara menggunakannya untuk membuat antrian serial? DispatchQueue.init (label:, qos:, atribut:, autoreleaseFrequency:, target
:)
@ nr5 Antrian adalah serial secara default, jadi cukup untuk digunakan hanya DispatchQueue(label: "your-label")untuk antrian serial. Params tambahan semua memiliki nilai default.
jbg

Jawaban:

1131

Membuat antrian bersamaan

let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)
concurrentQueue.sync {

}  

Buat antrian serial

let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync { 

}

Dapatkan antrian utama secara tidak sinkron

DispatchQueue.main.async {

}

Dapatkan antrian utama secara sinkron

DispatchQueue.main.sync {

}

Untuk mendapatkan salah satu utas latar belakang

DispatchQueue.global(qos: .background).async {

}

Xcode 8.2 beta 2:

Untuk mendapatkan salah satu utas latar belakang

DispatchQueue.global(qos: .default).async {

}

DispatchQueue.global().async {
    // qos' default value is ´DispatchQoS.QoSClass.default`
}

Jika Anda ingin belajar tentang menggunakan antrian ini. Lihat jawaban ini

iOS iOS yang malas 웃
sumber
3
Anda benar-benar dapat menghilangkan attributes: .serialsaat membuat antrian serial: let serialQueue = DispatchQueue(label: "queuename").
kean
15
Di Xcode 8 beta 4 tidak ada opsi serial sehingga Anda harus membuat antrean serial dengan menghilangkan atribut .concurrent in.
Oleg Sherman
Saya perlu mengakses DispatchQueue dari Swift3 ke objc tetapi mendapat kesalahan berikut Tidak dapat menginisialisasi variabel tipe '__strong dispatch_queue_t' (alias 'NSObject <OS_dispatch_queue> * __ kuat') dengan nilai dari tipe 'OS_dispatch_queue * _Nonnull' ketika melakukan background_quue_quue = [Antrian SwiftClass]; itu adalah variabel statis DispatchQueue di swift
ideerge
DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} di Swift 3.0 saya sudah mencoba dengan DispatchQueue.global (). Asynchronously (DispatchQueue.main) {self.mapView.add (self .mapPolyline)} tetapi keduanya menunjukkan kesalahan yang sama dengan "nilai tipe dispathQuoue tidak memiliki anggota secara sinkron"
Abirami Bala
1
dari kode OP, mengapa apple fokus menggunakan "com.swift3.imageQueue" . Saya melihat bahwa label memiliki 3 bagian. Mengapa demikian? apa artinya setiap bagian berdiri? Saya tidak mendapatkan format
Honey
55

Kompilasi di bawah> = Swift 3 . Contoh ini mengandung sebagian besar sintaks yang kita butuhkan.

QoS - kualitas baru sintaksis layanan

weak self - Mengganggu mempertahankan siklus

jika diri tidak tersedia, jangan lakukan apa pun

async global utility queue- untuk permintaan jaringan, tidak menunggu hasilnya, itu adalah antrian bersamaan, blok (biasanya) tidak menunggu ketika dimulai. Pengecualian untuk antrian konkuren bisa, ketika batas tugasnya telah tercapai sebelumnya, maka antrian sementara berubah menjadi antrian serial dan menunggu sampai beberapa tugas sebelumnya dalam antrian itu selesai.

async main queue- untuk menyentuh UI, blok tidak menunggu hasilnya, tetapi menunggu slotnya di awal. Antrian utama adalah antrian serial.

Tentu saja, Anda perlu menambahkan beberapa pengecekan kesalahan pada ...

DispatchQueue.global(qos: .utility).async { [weak self] () -> Void in

    guard let strongSelf = self else { return }

    strongSelf.flickrPhoto.loadLargeImage { loadedFlickrPhoto, error in

        if error != nil {
            print("error:\(error)")
        } else {
            DispatchQueue.main.async { () -> Void in
                activityIndicator.removeFromSuperview()
                strongSelf.imageView.image = strongSelf.flickrPhoto.largeImage
            }
        }
    }
}
t1ser
sumber
6
Saat
menulis
Terima kasih atas contoh [diri lemah]!
seperti
1
Lebih baik untuk guardyang selftidak nildi atas, sehingga tidak ada kode dijalankan jika itu nil, misalnya, guard strongSelf = self else { return }.
Scott Gardner
@ t1 Bisakah Anda memberi tahu saya di mana saya dapat menemukan dokumentasi untuk GCD yang ditulis dengan kode dalam Swift 3? Saya hanya menemukan satu ditulis di Objective C . Seseorang di sini mengarahkan saya ke video dari WWDC, tetapi saya ingin membaca dokumentasi resmi dengan contoh di Swift 3 dan tidak ada cara untuk menemukannya.
bibscy
1
Jangan gunakan .global(qos: .background)untuk IO (permintaan jaringan). Gunakan .global(qos: .default)atau .global(qos: .utility)sebagai gantinya.
Pedro Paulo Amorim
28

Dikompilasi dalam XCode 8, Swift 3 https://github.com/rpthomas/Jedisware

 @IBAction func tap(_ sender: AnyObject) {

    let thisEmail = "emailaddress.com"
    let thisPassword = "myPassword" 

    DispatchQueue.global(qos: .background).async {

        // Validate user input

        let result = self.validate(thisEmail, password: thisPassword)

        // Go back to the main thread to update the UI
        DispatchQueue.main.async {
            if !result
            {
                self.displayFailureAlert()
            }

        }
    }

}
R Thomas
sumber
12

Karena pertanyaan OP sudah dijawab di atas, saya hanya ingin menambahkan beberapa pertimbangan kecepatan:

Itu membuat banyak perbedaan apa kelas prioritas yang Anda tetapkan untuk fungsi async Anda di DispatchQueue.global .

Saya tidak merekomendasikan menjalankan tugas dengan prioritas .background thread terutama pada iPhone X di mana tugas tersebut tampaknya dialokasikan pada core berdaya rendah.

Berikut adalah beberapa data nyata dari fungsi intensif komputasi yang membaca dari file XML (dengan buffering) dan melakukan interpolasi data:

Nama perangkat / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18.7s / 6.3s / 1.8s / 1.8s / 1.8s
  2. iPhone 7: 4.6s / 3.1s / 3.0s / 2.8s / 2.6s
  3. iPhone 5: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s

Perhatikan bahwa kumpulan data tidak sama untuk semua perangkat. Ini yang terbesar di iPhone X dan yang terkecil di iPhone 5s.

Cosmin
sumber
1
Info bagus
Bantu
1
@Myk Jika pengguna telah menginisiasi dan / atau sedang menunggu hasil, Anda harus menggunakan .userInitiated atau .userInteractive sehingga operasi lain akan di-backtrack. Dalam kebanyakan kasus lain. Kesalahan akan menjadi pilihan yang baik.
Cosmin
6

Saya melakukan ini dan ini sangat penting jika Anda ingin menyegarkan UI Anda untuk menampilkan data baru tanpa memperhatikan pengguna seperti di UITableView atau UIPickerView.

    DispatchQueue.main.async
 {
   /*Write your thread code here*/
 }
Asfand Shabbir
sumber
3
 DispatchQueue.main.async {
          self.collectionView?.reloadData() // Depends if you were populating a collection view or table view
    }


OperationQueue.main.addOperation {
    self.lblGenre.text = self.movGenre
}

// gunakan Operation Queue jika Anda perlu mengisi objek (label, imageview, textview) pada viewcontroller Anda

Fritz Gerald Moran
sumber
2
   let concurrentQueue = dispatch_queue_create("com.swift3.imageQueue", DISPATCH_QUEUE_CONCURRENT) //Swift 2 version

   let concurrentQueue = DispatchQueue(label:"com.swift3.imageQueue", attributes: .concurrent) //Swift 3 version

Saya mengerjakan ulang kode Anda di Xcode 8, Swift 3 dan perubahannya ditandai berbeda dengan versi Swift 2 Anda.

gosborne3
sumber
Ini terlihat lebih bersih daripada yang saya tulis. Terima kasih.
gosborne3
2

Cepat 3

Anda ingin memanggil beberapa penutupan dalam kode cepat maka Anda ingin mengubah di storyboard ya semua jenis perubahan milik tampilan aplikasi Anda akan crash

tetapi Anda ingin menggunakan metode pengiriman aplikasi Anda tidak akan crash

metode async

DispatchQueue.main.async 
{
 //Write code here                                   

}

metode sinkronisasi

DispatchQueue.main.sync 
{
     //Write code here                                  

}
Amul4608
sumber
Saya ingin menggunakan metode async dalam waktu layanan panggilan kode saya adalah DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") sebagai! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animated: false)}
Amul4608
1
Jangan pernah gunakanDispatchQueue.main.sync
trickster77777
Sinkronisasi panggilan pada antrian utama pasti akan menyebabkan masalah.
Tofu Warrior
2
DispatchQueue.main.async(execute: {

// write code

})

Antrian serial:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Antrian bersamaan:

 let concurrent = DispatchQueue(label: "Queuename", attributes: .concurrent)

concurrent.sync {

 //Code Here
}
Hitesh Chauhan
sumber
Ini tidak membuat antrian pengiriman, itu hanya menempatkan Anda pada antrian utama setelah satu centang melalui run loop.
buildsucceeded
1

Untuk Swift 3

   DispatchQueue.main.async {
        // Write your code here
    }
Joseph Mikko Manoza
sumber
@Moritz saya sangat setuju, sayangnya.
Orkhan Alikhanov
1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }
Dalam
sumber
1

Perbarui untuk cepat 5

Antrian serial

let serialQueue = DispatchQueue.init(label: "serialQueue")
serialQueue.async {
    // code to execute
}

Antrian Bersamaan

let concurrentQueue = DispatchQueue.init(label: "concurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

concurrentQueue.async {
// code to execute
}

Dari dokumentasi Apple :

Parameter

label

Label string untuk dilampirkan ke antrian untuk mengidentifikasi secara unik di alat debugging seperti Instrumen, sampel, stackshots, dan laporan kerusakan. Karena aplikasi, perpustakaan, dan kerangka kerja semuanya dapat membuat antrian pengiriman sendiri, gaya penamaan DNS-terbalik (com.example.myqueue) direkomendasikan. Parameter ini opsional dan bisa NULL.

qos

Tingkat kualitas layanan untuk dikaitkan dengan antrian. Nilai ini menentukan prioritas di mana sistem menjadwalkan tugas untuk dieksekusi. Untuk daftar nilai yang mungkin, lihat DispatchQoS.QoSClass.

atribut

Atribut untuk dikaitkan dengan antrian. Sertakan atribut konkuren untuk membuat antrian pengiriman yang menjalankan tugas secara bersamaan. Jika Anda menghilangkan atribut itu, antrian pengiriman menjalankan tugas secara seri.

autoreleaseFrequency

Frekuensi untuk melakukan autorelease objek yang dibuat oleh blok yang dijadwalkan antrian. Untuk daftar nilai yang mungkin, lihat DispatchQueue.AutoreleaseFrequency .

target

Antrean target untuk menjalankan blok. Tentukan DISPATCH_TARGET_QUEUE_DEFAULT jika Anda ingin sistem memberikan antrian yang sesuai untuk objek saat ini.

Mithra Singam
sumber
-3

itu sekarang hanya:

let serialQueue = DispatchQueue(label: "my serial queue")

default adalah serial, untuk mendapatkan bersamaan, Anda menggunakan argumen atribut opsional .concurrent

tylernol
sumber
Anda sebaiknya memperbarui jawaban Anda dengan menambahkan seiralQueue.async {}. @tylemol
DawnSong
-3
DispatchQueue.main.async(execute: {
   // code
})
Hitesh Chauhan
sumber
Terima kasih atas cuplikan kode ini, yang dapat memberikan bantuan segera. Penjelasan yang tepat akan sangat meningkatkan nilai pendidikannya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat bagi pembaca masa depan dengan pertanyaan yang serupa, tetapi tidak sama. Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Toby Speight
-4

Anda dapat membuat antrian pengiriman menggunakan kode ini di swift 3.0

DispatchQueue.main.async
 {
   /*Write your code here*/
 }

   /* or */

let delayTime = DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)                   
DispatchQueue.main.asyncAfter(deadline: delayTime)
{
  /*Write your code here*/
}
Nand Parikh
sumber
1
Maaf, itu tidak membuat antrian pengiriman, yang mengakses antrian utama setelah satu centang melalui run loop.
buildsucceeded