So erstellen Sie eine Versandwarteschlange in Swift 3


403

In Swift 2 konnte ich eine Warteschlange mit folgendem Code erstellen:

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

Dies wird jedoch in Swift 3 nicht kompiliert.

Was ist die bevorzugte Methode, um dies in Swift 3 zu schreiben?



Swift 4 verfügt über 3 zusätzliche Parameter zum Erstellen einer seriellen Warteschlange. Wie verwende ich sie, um eine serielle Warteschlange zu erstellen? DispatchQueue.init (label :, qos :, Attribute :, autoreleaseFrequency :, target
:)

@ nr5 Warteschlangen sind standardmäßig seriell, daher reicht es aus, sie nur DispatchQueue(label: "your-label")für eine serielle Warteschlange zu verwenden. Die zusätzlichen Parameter haben alle Standardwerte.
jbg

Antworten:


1131

Erstellen einer gleichzeitigen Warteschlange

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

}  

Erstellen Sie eine serielle Warteschlange

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

}

Hauptwarteschlange asynchron abrufen

DispatchQueue.main.async {

}

Hauptwarteschlange synchron abrufen

DispatchQueue.main.sync {

}

Um einen der Hintergrund-Threads zu erhalten

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

}

Xcode 8.2 Beta 2:

Um einen der Hintergrund-Threads zu erhalten

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

}

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

Wenn Sie mehr über die Verwendung dieser Warteschlangen erfahren möchten, lesen Sie diese Antwort


3
Sie können attributes: .serialbeim Erstellen einer seriellen Warteschlange tatsächlich weglassen : let serialQueue = DispatchQueue(label: "queuename").
Kean

15
In Xcode 8 Beta 4 gibt es keine .serial-Option, sodass Sie eine serielle Warteschlange erstellen müssen, indem Sie die .concurrent-Attribute weglassen.
Oleg Sherman

Ich muss von Swift3 in objc auf die DispatchQueue zugreifen, habe aber den folgenden Fehler erhalten. Eine Variable vom Typ '__strong dispatch_queue_t' (auch bekannt als 'NSObject <OS_dispatch_queue> * __ strong') mit einem Wert vom Typ 'OS_dispatch_queue * _Nonnull' kann beim Dispatch_queue_t nicht ausgeführt werden = [SwiftClass Queue]; das ist eine statische Variable von DispatchQueue in swift
ideerge

DispatchQueue.main.asynchronously (DispatchQueue.main) {self.mapView.add (self.mapPolyline)} in Swift 3.0 habe ich mit DispatchQueue.global () versucht. Asynchronously (DispatchQueue.main) {self.mapView.add (self .mapPolyline)}, aber beide zeigen den gleichen Fehler wie "Wert vom Typ dispathQuoue hat kein Mitglied asynchron"
Abirami Bala

1
aus dem Code des OP, warum tut Apfel Fokus auf der Verwendung „com.swift3.imageQueue“ . Ich sehe, dass das Etikett 3 Teile hat. Warum ist das so? Wofür steht jedes Teil? Ich verstehe die Formatierung nicht
Honey

55

Kompiliert unter> = Swift 3 . Dieses Beispiel enthält den größten Teil der Syntax, die wir benötigen.

QoS - neue Syntax für Servicequalität

weak self - Haltezyklen zu unterbrechen

Wenn Selbst nicht verfügbar ist, tun Sie nichts

async global utility queue- Bei Netzwerkabfragen wird nicht auf das Ergebnis gewartet, es handelt sich um eine gleichzeitige Warteschlange. Der Block wartet (normalerweise) nicht beim Start. Eine Ausnahme für eine gleichzeitige Warteschlange könnte sein, dass die Warteschlange, wenn ihr Aufgabenlimit zuvor erreicht wurde, vorübergehend in eine serielle Warteschlange umgewandelt wird und wartet, bis eine vorherige Aufgabe in dieser Warteschlange abgeschlossen ist.

async main queue- Zum Berühren der Benutzeroberfläche wartet der Block nicht auf das Ergebnis, sondern zu Beginn auf seinen Steckplatz. Die Hauptwarteschlange ist eine serielle Warteschlange.

Natürlich müssen Sie hier einige Fehlerprüfungen hinzufügen ...

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
Wenn Sie in Swift 3 codieren, gewöhnen Sie sich daran, 30% Ihres vorherigen Codes zu
komprimieren

Danke für das Beispiel [schwaches Selbst]!
Imike

1
Es ist besser, guarddass dies selfnicht niloben steht, so dass keiner der Codes ausgeführt wird, wenn es nilz guard strongSelf = self else { return }.
Scott Gardner

@ t1 Können Sie mir sagen, wo ich die Dokumentation für GCD finden kann, die mit Code in Swift 3 geschrieben wurde? Ich habe nur den in Ziel C geschriebenen gefunden . Jemand hier hat mich auf ein Video von WWDC hingewiesen, aber ich möchte die offizielle Dokumentation mit Beispielen in Swift 3 lesen und es gibt keine Möglichkeit, sie zu finden.
bibscy

1
Nicht .global(qos: .background)für E / A (Netzwerkanforderung) verwenden. Verwenden Sie .global(qos: .default)oder .global(qos: .utility)stattdessen.
Pedro Paulo Amorim

28

Kompiliert 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

Da die OP-Frage bereits oben beantwortet wurde, möchte ich nur einige Überlegungen zur Geschwindigkeit hinzufügen:

Es macht einen großen Unterschied, welche Prioritätsklasse Sie Ihrer asynchronen Funktion in DispatchQueue.global zuweisen .

Ich empfehle nicht, Aufgaben mit der Priorität .background thread auszuführen, insbesondere auf dem iPhone X, wo die Aufgabe auf den Kernen mit geringem Stromverbrauch zugewiesen zu sein scheint.

Hier sind einige reale Daten aus einer rechenintensiven Funktion, die aus einer XML-Datei (mit Pufferung) liest und Dateninterpolation durchführt:

Gerätename / .background / .utility / .default / .userInitiated / .userInteractive

  1. iPhone X: 18,7 s / 6,3 s / 1,8 s / 1,8 s / 1,8 s
  2. iPhone 7: 4,6 s / 3,1 s / 3,0 s / 2,8 s / 2,6 s
  3. iPhone 5s: 7,3s / 6,1s / 4,0s / 4,0s / 3,8s

Beachten Sie, dass der Datensatz nicht für alle Geräte gleich ist. Es ist das größte auf dem iPhone X und das kleinste auf dem iPhone 5s.


1
Tolle Infos. Hat mir geholfen
Morgz

1
@Myk Wenn der Benutzer initiiert hat und / oder auf die Ergebnisse wartet, sollten Sie .userInitiated oder .userInteractive verwenden, damit alle anderen Vorgänge zurückverfolgt werden. In den meisten anderen Fällen wäre .default eine gute Wahl.
Cosmin

6

Ich habe dies getan und dies ist besonders wichtig, wenn Sie Ihre Benutzeroberfläche aktualisieren möchten, um neue Daten anzuzeigen, ohne dass der Benutzer dies wie in UITableView oder UIPickerView bemerkt.

    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
}

// Verwenden Sie die Operationswarteschlange, wenn Sie die Objekte (Beschriftungen, Bildansicht, Textansicht) auf Ihrem Viewcontroller füllen müssen


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

Ich habe Ihren Code in Xcode 8, Swift 3 überarbeitet und die Änderungen sind im Gegensatz zu Ihrer Swift 2-Version markiert.


Das sieht sauberer aus als das, was ich geschrieben habe. Vielen Dank.
Gosborne3

2

Swift 3

Wenn Sie einen Abschluss in schnellem Code aufrufen möchten, möchten Sie ihn im Storyboard ändern. Jede Art von Änderung gehört zur Ansicht, dass Ihre Anwendung abstürzt

Wenn Sie jedoch die Versandmethode verwenden möchten, stürzt Ihre Anwendung nicht ab

asynchrone Methode

DispatchQueue.main.async 
{
 //Write code here                                   

}

Synchronisierungsmethode

DispatchQueue.main.sync 
{
     //Write code here                                  

}

Ich möchte die asynchrone Methode in der Dienstaufrufzeit verwenden. Mein Code lautet DispatchQueue.main.async {let objstory1 = self.storyboard? .InstantiateViewController (withIdentifier: "HomeViewController") as! HomeViewController _ = self.navigationController? .PushViewController (objstory1, animiert: false)}
Amul4608

1
Niemals benutzenDispatchQueue.main.sync
trickster77777

Synchronisierungsanrufe in der Hauptwarteschlange verursachen definitiv Probleme.
Tofu-Krieger

2
DispatchQueue.main.async(execute: {

// write code

})

Serielle Warteschlange:

let serial = DispatchQueue(label: "Queuename")

serial.sync { 

 //Code Here

}

Gleichzeitige Warteschlange:

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

concurrent.sync {

 //Code Here
}

Dadurch wird keine Versandwarteschlange erstellt, sondern Sie werden nur nach einem Tick durch die Ausführungsschleife in die Hauptwarteschlange gestellt.
Builds erfolgreich


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

 // your code

 }

1

Update für Swift 5

Serielle Warteschlange

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

Gleichzeitige Warteschlange

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

concurrentQueue.async {
// code to execute
}

Aus der Apple-Dokumentation :

Parameter

Etikette

Eine Zeichenfolgenbezeichnung, die an die Warteschlange angehängt werden soll, um sie in Debugging-Tools wie Instruments, Sample, Stackshots und Absturzberichten eindeutig zu identifizieren. Da Anwendungen, Bibliotheken und Frameworks ihre eigenen Versandwarteschlangen erstellen können, wird ein Reverse-DNS-Benennungsstil (com.example.myqueue) empfohlen. Dieser Parameter ist optional und kann NULL sein.

qos

Das Quality-of-Service-Level, das der Warteschlange zugeordnet werden soll. Dieser Wert bestimmt die Priorität, mit der das System Aufgaben für die Ausführung plant. Eine Liste möglicher Werte finden Sie unter DispatchQoS.QoSClass.

Attribute

Die Attribute, die der Warteschlange zugeordnet werden sollen. Fügen Sie das Attribut concurrent hinzu, um eine Versandwarteschlange zu erstellen, in der Aufgaben gleichzeitig ausgeführt werden. Wenn Sie dieses Attribut weglassen, führt die Versandwarteschlange Aufgaben seriell aus.

AutoreleaseFrequency

Die Häufigkeit, mit der Objekte, die von den von der Warteschlange geplanten Blöcken erstellt wurden, automatisch freigegeben werden. Eine Liste möglicher Werte finden Sie unter DispatchQueue.AutoreleaseFrequency .

Ziel

Die Zielwarteschlange, in der Blöcke ausgeführt werden sollen. Geben Sie DISPATCH_TARGET_QUEUE_DEFAULT an, wenn das System eine Warteschlange bereitstellen soll, die für das aktuelle Objekt geeignet ist.


-3

es ist jetzt einfach:

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

Der Standardwert ist seriell. Um gleichzeitig zu werden, verwenden Sie das optionale Attributargument .concurrent


Sie sollten Ihre Antwort besser durch Hinzufügen aktualisieren seiralQueue.async {}. @ Tylemol
DawnSong

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

Vielen Dank für dieses Code-Snippet, das möglicherweise sofortige Hilfe bietet. Eine richtige Erklärung würde den Bildungswert erheblich verbessern , indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und sie für zukünftige Leser mit ähnlichen, aber nicht identischen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, und geben Sie an, welche Einschränkungen und Annahmen gelten.
Toby Speight

-4

Mit diesem Code können Sie in Swift 3.0 eine Versandwarteschlange erstellen

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
Es wird leider keine Versandwarteschlange erstellt, sondern es wird nach einem Tick durch die Ausführungsschleife auf die Hauptwarteschlange zugegriffen.
Builds erfolgreich
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.