Come creare la coda di invio in Swift 3


403

In Swift 2, sono stato in grado di creare una coda con il seguente codice:

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

Ma questo non si compila in Swift 3.

Qual è il modo preferito di scrivere questo in Swift 3?



Swift 4 ha 3 parametri extra per creare una coda seriale. Come usarli per creare una coda seriale? DispatchQueue.init (etichetta:, QoS:, attributi:, autoreleaseFrequency:, bersaglio:)
nr5

@ nr5 Le code sono di serie per impostazione predefinita, quindi è sufficiente utilizzare solo DispatchQueue(label: "your-label")per una coda seriale. Tutti i parametri aggiuntivi hanno valori predefiniti.
jbg

Risposte:


1131

Creazione di una coda simultanea

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

}  

Crea una coda seriale

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

}

Ottieni la coda principale in modo asincrono

DispatchQueue.main.async {

}

Ottieni la coda principale in modo sincrono

DispatchQueue.main.sync {

}

Per ottenere uno dei thread in background

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

}

Xcode 8.2 beta 2:

Per ottenere uno dei thread in background

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

}

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

Se vuoi imparare a usare queste code. Vedi questa risposta


3
Si può effettivamente omettere attributes: .serialquando si crea una coda di serie: let serialQueue = DispatchQueue(label: "queuename").
Kean,

15
In Xcode 8 beta 4 non esiste un'opzione .serial, quindi è necessario creare una coda seriale omettendo la .concurrent negli attributi.
Oleg Sherman,

Ho bisogno di accedere a DispatchQueue da Swift3 in objc ma ho ottenuto il seguente errore Impossibile inizializzare una variabile di tipo '__strong dispatch_queue_t' (aka 'NSObject <OS_dispatch_queue> * __ strong') con un valore di tipo 'OS_dispatch_queue * _Nonnull' quando si fa dispatch_Que = [Coda SwiftClass]; questa è una variabile statica di DispatchQueue in swift
ideerge,

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} in Swift 3.0 ho provato con DispatchQueue.global (). Asincrono (dispatchQueue.main) {self.mapView.add (self.mapView.add .mapPolyline)} ma entrambi mostrano lo stesso errore di "valore del tipo dispathQuoue non ha alcun membro in modo asincrono"
Abirami Bala

1
dal codice dell'OP, perché apple si concentra sull'uso di "com.swift3.imageQueue" . Vedo che l'etichetta ha 3 parti. Perché? cosa rappresenta ogni parte? Non ottengo la formattazione
Honey

55

Compila sotto> = Swift 3 . Questo esempio contiene la maggior parte della sintassi di cui abbiamo bisogno.

QoS: nuova sintassi della qualità del servizio

weak self - interrompere i cicli di mantenimento

se il sé non è disponibile, non fare nulla

async global utility queue- per query di rete, non attende il risultato, è una coda simultanea, il blocco (di solito) non attende all'avvio. Un'eccezione per una coda concorrente potrebbe essere, quando il limite di attività è stato precedentemente raggiunto, quindi la coda si trasforma temporaneamente in una coda seriale e attende fino al completamento di alcune attività precedenti in quella coda.

async main queue- per toccare l'interfaccia utente, il blocco non attende il risultato, ma attende il suo slot all'inizio. La coda principale è una coda seriale.

Ovviamente, devi aggiungere un po 'di controllo degli errori a questo ...

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
Quando scrivi il codice in Swift 3, abituati a condensare ed eliminare il 30% del tuo codice precedente :-)
t1ser

Grazie per l'esempio di [sé debole]!
imike

1
È meglio guardche selfnon sia nilnella parte superiore, quindi nessuno del codice viene eseguito se è nil, ad esempio guard strongSelf = self else { return }.
Scott Gardner,

@ t1 Potresti dirmi dove posso trovare la documentazione per GCD scritta con il codice in Swift 3? Ho trovato solo quello scritto in Objective C . Qualcuno qui mi stava indicando un video del WWDC, ma voglio leggere la documentazione ufficiale con esempi in Swift 3 e non c'è modo di trovarlo.
bibscy,

1
Non utilizzare .global(qos: .background)per IO (richiesta di rete). Usa .global(qos: .default)o .global(qos: .utility)invece.
Pedro Paulo Amorim,

28

Compilato in 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

Poiché alla domanda OP è già stata data una risposta sopra, voglio solo aggiungere alcune considerazioni sulla velocità:

Fa molta differenza quale classe di priorità assegni alla tua funzione asincrona in DispatchQueue.global .

Non consiglio di eseguire attività con .background priorità del thread particolare su iPhone X in cui l'attività sembra essere allocata sui core a bassa potenza.

Ecco alcuni dati reali da una funzione ad alta intensità computazionale che legge da un file XML (con buffering) ed esegue l'interpolazione dei dati:

Nome dispositivo / .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

Si noti che il set di dati non è lo stesso per tutti i dispositivi. È il più grande su iPhone X e il più piccolo su iPhone 5s.


1
Informazioni fantastiche. Mi ha aiutato
Morgz,

1
@Myk Se l'utente ha avviato e / o è in attesa dei risultati, è necessario utilizzare .userInitiated o .userInteractive in modo che qualsiasi altra operazione venga retrocessa. Nella maggior parte degli altri casi .default sarebbe una buona scelta.
Cosmin

6

L'ho fatto e questo è particolarmente importante se si desidera aggiornare l'interfaccia utente per mostrare nuovi dati senza che l'utente se ne accorga come in UITableView o 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
}

// usa la coda operazioni se devi popolare gli oggetti (etichette, visualizzazione immagine, visualizzazione testo) sul tuo viewcontroller


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

Ho rielaborato il tuo codice in Xcode 8, Swift 3 e le modifiche sono contrassegnate in contrasto con la tua versione di Swift 2.


Sembra più pulito di quello che ho scritto. Grazie.
gosborne3,

2

Swift 3

vuoi chiamare un po 'di chiusura nel codice rapido quindi vuoi cambiare nello storyboard ya qualsiasi tipo di modifica offri per vedere la tua applicazione andrà in crash

ma si desidera utilizzare il metodo di invio dell'applicazione non si arresta in modo anomalo

metodo asincrono

DispatchQueue.main.async 
{
 //Write code here                                   

}

metodo di sincronizzazione

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Voglio usare il metodo asincrono al momento della chiamata del servizio il mio codice è DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") as! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animato: false)}
Amul4608

1
Non usare maiDispatchQueue.main.sync
trickster77777,

La sincronizzazione delle chiamate sulla coda principale causerà sicuramente problemi.
Tofu Warrior,

2
DispatchQueue.main.async(execute: {

// write code

})

Coda seriale:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Coda concorrente:

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

concurrent.sync {

 //Code Here
}

Questo non crea una coda di invio, ti mette semplicemente nella coda principale dopo un segno di spunta nel ciclo di esecuzione.
build completata


1
 let newQueue = DispatchQueue(label: "newname")
 newQueue.sync { 

 // your code

 }

1

Aggiornamento per swift 5

Coda seriale

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

Coda simultanea

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

concurrentQueue.async {
// code to execute
}

Dalla documentazione Apple :

parametri

etichetta

Un'etichetta di stringa da allegare alla coda per identificarla in modo univoco in strumenti di debug come strumenti, campioni, stackshots e rapporti sugli arresti anomali. Poiché le applicazioni, le librerie e i framework possono tutti creare le proprie code di invio, si consiglia uno stile di denominazione DNS inverso (com.example.myqueue). Questo parametro è facoltativo e può essere NULL.

QoS

Il livello di qualità del servizio da associare alla coda. Questo valore determina la priorità con cui il sistema pianifica le attività per l'esecuzione. Per un elenco di possibili valori, vedere DispatchQoS.QoSClass.

attributi

Gli attributi da associare alla coda. Includere l'attributo simultaneo per creare una coda di invio che esegue attività contemporaneamente. Se si omette tale attributo, la coda di invio esegue le attività in serie.

autoreleaseFrequency

La frequenza con cui rilasciare automaticamente gli oggetti creati dai blocchi pianificati dalla coda. Per un elenco di possibili valori, vedere DispatchQueue.AutoreleaseFrequency .

bersaglio

La coda di destinazione su cui eseguire i blocchi. Specificare DISPATCH_TARGET_QUEUE_DEFAULT se si desidera che il sistema fornisca una coda appropriata per l'oggetto corrente.


-3

ora è semplicemente:

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

il valore predefinito è seriale, per essere simultanei, si utilizza l'argomento degli attributi facoltativi .concurrent


Faresti meglio ad aggiornare la tua risposta aggiungendo seiralQueue.async {}. @tylemol
DawnSong

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

Grazie per questo frammento di codice, che può fornire un aiuto immediato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore educativo mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con domande simili, ma non identiche. Si prega di modificare la risposta di aggiungere una spiegazione, e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
Toby Speight,

-4

Puoi creare una coda di invio usando questo codice in 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
Spiacenti, non si sta creando una coda di invio, ma si accede alla coda principale dopo un segno di spunta nel ciclo di esecuzione.
build completata
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.