Як створити диспетчерську чергу в Swift 3


403

У Swift 2 мені вдалося створити чергу із наступним кодом:

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

Але це не компілюється у Swift 3.

Який найкращий спосіб написати це у Swift 3?



У Swift 4 є 3 додаткові параметри для створення послідовної черги. Як використовувати їх для створення послідовної черги? DispatchQueue.init (label:, qos:, attributes:, autoreleaseFrequency:, target:)
nr5

@ nr5 Черги за замовчуванням є послідовними, тому достатньо лише використовувати їх DispatchQueue(label: "your-label")для чергової черги. Усі додаткові параметри мають значення за замовчуванням.
jbg

Відповіді:


1131

Створення паралельної черги

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

}  

Створіть послідовну чергу

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

}

Отримайте головну чергу асинхронно

DispatchQueue.main.async {

}

Отримайте основну чергу синхронно

DispatchQueue.main.sync {

}

Щоб отримати одну з фонових ниток

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

}

Xcode 8.2 бета-версія 2:

Щоб отримати одну з фонових ниток

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

}

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

Якщо ви хочете дізнатися про використання цих черг. Перегляньте цю відповідь


3
Ви дійсно можете пропустити attributes: .serialпри створенні послідовної черги: let serialQueue = DispatchQueue(label: "queuename").
kean

15
У Xcode 8 beta 4 немає .serial опції, тому вам доведеться створювати послідовну чергу, опускаючи .concurrent в атрибутах.
Олег Шерман

Мені потрібно отримати доступ до DispatchQueue з Swift3 в objc, але отримана наступна помилка. Неможливо ініціалізувати змінну типу '__strong dispatch_queue_t' (він же 'NSObject <OS_dispatch_queue> * __ strong') з ревальвацією типу 'OS_dispatch_queue * _Nontll_' = [Черга SwiftClass]; це статична змінна DispatchQueue в швидкому
ideerge

DispatchQueue.main.asynchronmous (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} у Swift 3.0 я намагався з DispatchQueue.global (). Асинхронно (DispatchQueue.main) {self.mapView.add (self .mapPolyline)}, але обидва показують ту саму помилку, що і "значення типу dispathQuoue не має асинхронного члена"
Abirami Bala

1
з коду ОП, чому яблуко фокусується на використанні "com.swift3.imageQueue" . Я бачу, що ця етикетка має 3 частини. Чому так? що означає кожна частина? Я не отримую форматування
Honey

55

Компілюється під> = Швидкий 3 . Цей приклад містить більшу частину потрібного нам синтаксису.

QoS - новий синтаксис якості обслуговування

weak self - для порушення циклів утримування

якщо самодоступність недоступна, нічого не робіть

async global utility queue- для мережевого запиту, не чекає результату, це паралельна черга, блок (зазвичай) не чекає, коли його запустити. Виняток для паралельної черги може бути, коли його ліміт завдань був досягнутий раніше, тоді черга тимчасово перетворюється на послідовну чергу і чекає, поки якесь попереднє завдання в цій черзі не завершиться.

async main queue- для торкання інтерфейсу, блок не чекає результату, а чекає свого слота на старті. Основна черга - це послідовна черга.

Звичайно, до цього потрібно додати деяку перевірку помилок ...

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

6
Під час кодування у Swift 3 звикніть до конденсації та видалення 30% попереднього коду :-)
t1ser

Дякую за приклад [слабкий я]!
imike

1
Краще до guardцьогоself НЕ nilна вершині, так що жоден з кодів не виконується , якщо це nil, наприклад, guard strongSelf = self else { return }.
Скотт Гарднер

@ t1 Чи не могли б ви сказати мені, де я можу знайти документацію для GCD, написану з кодом у Swift 3? Я знайшов лише те, що написано в «Цілі С» . Хтось тут вказував мені на відео з WWDC, але я хочу прочитати офіційну документацію із прикладами в Swift 3, і немає можливості її знайти.
bibscy

1
Не використовуйте .global(qos: .background)для IO (запит мережі). Використовуйте .global(qos: .default)або .global(qos: .utility)замість цього.
Педро Паулу Аморім

28

Складено у 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()
            }

        }
    }

}

12

Оскільки на питання щодо ОП вже відповіли вище, я просто хочу додати деякі міркування щодо швидкості:

Це має велику різницю, який пріоритетний клас ви присвоюєте своїй функції асинхронізації в DispatchQueue.global .

Я не рекомендую виконувати завдання з .background пріоритетом потоку особливо на iPhone X, де завдання, здається, розподілено на ядрах малої потужності.

Ось деякі реальні дані з обчислювально інтенсивної функції, яка зчитує файл XML (з буферизацією) та виконує інтерполяцію даних:

Назва пристрою / .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 5s: 7.3s / 6.1s / 4.0s / 4.0s / 3.8s

Зауважте, що набір даних не однаковий для всіх пристроїв. Це найбільший на iPhone X і найменший на iPhone 5s.


1
Чудова інформація. Допомогли мені
Моргз

1
@Myk Якщо користувач ініціював та / або чекає результатів, ви повинні використовувати .userInitiated або .userInteractive, щоб будь-яка інша операція була відкликана. У більшості інших випадків .default буде хорошим вибором.
Космін

6

Я зробив це, і це особливо важливо, якщо ви хочете оновити інтерфейс користувача, щоб показувати нові дані, не помічаючи користувачів, як у UITableView або UIPickerView.

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

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
}

// використовувати Операційну чергу, якщо вам потрібно заповнити об'єкти (мітки, перегляд зображень, перегляд тексту) на своєму контролері перегляду


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

Я переробив ваш код у Xcode 8, Swift 3, і зміни позначені на відміну від вашої версії Swift 2.


Це виглядає чистіше, ніж те, що я написав. Дякую.
gosborne3

2

Швидкий 3

ви хочете зателефонувати у закритий код, тоді ви хочете змінити в раскадровці, будь-яка зміна вибору належить, щоб переглянути вашу програму.

але ви хочете скористатися методом диспетчеризації, ваша програма не вийде з ладу

метод асинхронізації

DispatchQueue.main.async 
{
 //Write code here                                   

}

метод синхронізації

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Я хочу використовувати метод async в час виклику служби, мій код - DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") як! HomeViewController _ = self.navigationController? .PushViewController (objstory1, анімований: false)}
Amul4608

1
Ніколи не використовуйтеDispatchQueue.main.sync
trickster77777

Синхронізувати дзвінки в основній черзі, безумовно, виникнуть проблеми.
Воїн Тофу

2
DispatchQueue.main.async(execute: {

// write code

})

Серійна черга:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Паралельна черга:

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

concurrent.sync {

 //Code Here
}

Це не створює диспетчерську чергу, вона просто ставить вас в основну чергу після одного галочки через цикл запуску.
будівництвовдале



1

Оновлення для швидкої 5

Серійна черга

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

Паралельна черга

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

concurrentQueue.async {
// code to execute
}

З документації Apple :

Параметри

етикетка

Мітка рядка, яку потрібно приєднати до черги, щоб однозначно ідентифікувати її в інструментах налагодження, таких як "Інструменти", "зразок", "стеки" та "звіти про збої". Оскільки програми, бібліотеки та фреймворки можуть створювати власні черги відправлення, рекомендується стиль імен зворотного DNS (com.example.myqueue). Цей параметр необов’язковий і може бути NULL.

qos

Рівень якості обслуговування для зв’язку з чергою. Це значення визначає пріоритет, з яким система планує завдання на виконання. Список можливих значень див. У DispatchQoS.QoSClass.

атрибути

Атрибути, що асоціюються з чергою. Включіть атрибут concurrent для створення черги відправлення, яка виконує завдання одночасно. Якщо цей атрибут пропущено, черга відправки виконує завдання послідовно.

autoreleaseFrequency

Частота автоматичної вивільнення об'єктів, створених блоками, які планує чергу. Список можливих значень див у розділі DispatchQueue.AutoreleaseFrequency .

цільовий

Цільова черга, за якою виконувати блоки. Вкажіть DISPATCH_TARGET_QUEUE_DEFAULT, якщо ви хочете, щоб система надавала чергу, відповідну поточному об'єкту.


-3

тепер просто:

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

за замовчуванням - послідовний, для отримання одночасного використання ви використовуєте аргумент необов'язкових атрибутів .concurrent


Краще оновіть свою відповідь, додавши seiralQueue.async {}. @tylemol
DawnSong

-3
DispatchQueue.main.async(execute: {
   // code
})

Дякуємо за цей фрагмент коду, який може надати негайну допомогу. Правильне пояснення значно покращило б його навчальну цінність, показавши, чому це хороше рішення проблеми, та зробило б її кориснішою для майбутніх читачів із подібними, але не однаковими питаннями. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Toby Speight

-4

Ви можете створити диспетчерську чергу за допомогою цього коду в 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*/
}

1
Вибачте, це не створює диспетчерську чергу, це доступ до головної черги після одного галочки через цикл запуску.
будівництвовдале
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.