425 Stimmen

Wie verwende ich einen Hintergrund-Thread in Swift?

Wie verwendet man Threading in Swift?

dispatchOnMainThread:^{

    NSLog(@"Block wird auf %s ausgeführt", dispatch_queue_get_label(dispatch_get_current_queue()));

}];

847voto

tobiasdm Punkte 9558

Swift 3.0+

Es wurde viel in Swift 3.0 modernisiert. Das Ausführen von etwas in einer Hintergrundwarteschlange sieht so aus:

DispatchQueue.global(qos: .userInitiated).async {
    print("Dies wird in einer Hintergrundwarteschlange ausgeführt")

    DispatchQueue.main.async {
        print("Dies wird in der Hauptwarteschlange ausgeführt, nach dem vorherigen Code im äußeren Block")
    }
}

Swift 1.2 durch 2.3

let qualityOfServiceClass = QOS_CLASS_USER_INITIATED
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    print("Dies wird in einer Hintergrundwarteschlange ausgeführt")

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        print("Dies wird in der Hauptwarteschlange ausgeführt, nach dem vorherigen Code im äußeren Block")
    })
})

Vor Swift 1.2 – Bekanntes Problem

In Swift 1.1 hat Apple die obige Syntax ohne einige Anpassungen nicht unterstützt. Das Übergeben von QOS_CLASS_USER_INITIATED hat tatsächlich nicht funktioniert, stattdessen verwenden Sie Int(QOS_CLASS_USER_INITIATED.value).

Weitere Informationen finden Sie in der Dokumentation von Apple

203voto

frouo Punkte 4531

Antwort von Dan Beaulieu in swift5 (funktioniert auch seit Swift 3.0.1).

Swift 5.0.1

extension DispatchQueue {

    static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async {
            background?()
            if let completion = completion {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                    completion()
                })
            }
        }
    }

}

Verwendung

DispatchQueue.background(delay: 3.0, background: {
    // etwas im Hintergrund machen
}, completion: {
    // wenn der Hintergrundjob beendet ist, warte 3 Sekunden und mache etwas im Hauptthread
})

DispatchQueue.background(background: {
    // etwas im Hintergrund machen
}, completion:{
    // wenn der Hintergrundjob beendet ist, mache etwas im Hauptthread
})

DispatchQueue.background(delay: 3.0, completion:{
    // nach 3 Sekunden etwas im Hauptthread machen
})

126voto

Dale Clifford Punkte 1511

Die beste Praxis besteht darin, eine wiederverwendbare Funktion zu definieren, auf die mehrmals zugegriffen werden kann.

WIEDERVERWENDBARE FUNKTION:

z.B. irgendwo wie AppDelegate.swift als globale Funktion.

func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
    dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
        background?()

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            completion?()
        }
    }
}

Hinweis: In Swift 2.0 ersetzen Sie oben QOS_CLASS_USER_INITIATED.value durch QOS_CLASS_USER_INITIATED.rawValue

VERWENDUNG:

A. Um einen Prozess im Hintergrund mit einer Verzögerung von 3 Sekunden auszuführen:

    backgroundThread(3.0, background: {
            // Ihre Hintergrundfunktion hier
    })

B. Um einen Prozess im Hintergrund auszuführen und dann eine Fertigstellung im Vordergrund auszuführen:

    backgroundThread(background: {
            // Ihre Funktion hier, die im Hintergrund ausgeführt werden soll
    },
    completion: {
            // Eine Funktion im Vordergrund auszuführen, wenn der Hintergrundthread abgeschlossen ist
    })

C. Um um 3 Sekunden zu verzögern - beachten Sie die Verwendung des Fertigstellungsparameters ohne Hintergrundparameter:

    backgroundThread(3.0, completion: {
            // Ihre verzögerte Funktion hier, die im Vordergrund ausgeführt werden soll
    })

58voto

Naresh Punkte 14268

In Swift 4.2 und Xcode 10.1

Wir haben drei Arten von Warteschlangen:

1. Haupt-Warteschlange: Die Haupt-Warteschlange ist eine serielle Warteschlange, die vom System erstellt wird und mit dem Hauptthread der Anwendung verbunden ist.

2. Globale Warteschlange: Die globale Warteschlange ist eine nebenläufige Warteschlange, die wir je nach Dringlichkeit der Aufgaben anfordern können.

3. Benutzerdefinierte Warteschlangen: können vom Benutzer erstellt werden. Benutzerdefinierte nebenläufige Warteschlangen werden immer einer der globalen Warteschlangen zugeordnet, indem eine Eigenschaft der Dienstgüte (QoS) angegeben wird.

DispatchQueue.main//Hauptthread
DispatchQueue.global(qos: .userInitiated)//Hohe Priorität
DispatchQueue.global(qos: .userInteractive)//Hohe Priorität (etwas höher als userInitiated)
DispatchQueue.global(qos: .background)//Niedrigste Priorität
DispatchQueue.global(qos: .default)//Normale Priorität (nach Hoch, aber vor Niedrig)
DispatchQueue.global(qos: .utility)//Niedrige Priorität
DispatchQueue.global(qos: .unspecified)//Fehlen von Qualität

All diese Warteschlangen können auf zwei Arten ausgeführt werden

1. Synchrone Ausführung

2. Asynchrone Ausführung

DispatchQueue.global(qos: .background).async {
    //Hier die Aufgabe erledigen
    DispatchQueue.main.async {
        //Hier die Benutzeroberfläche aktualisieren
    }
}

//Führe eine Aufgabe aus und aktualisiere die Benutzeroberfläche sofort.
DispatchQueue.global(qos: .userInitiated).async {  
    // Aufgabe ausführen
    DispatchQueue.main.async {  
        // Benutzeroberfläche aktualisieren
        self.tableView.reloadData()  
    }
}

//Funktion nach einiger Zeit aufrufen oder ausführen
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    //Hier die Funktion aufrufen
}

//Wenn Änderungen in der Benutzeroberfläche vorgenommen werden sollen, verwenden Sie dies
DispatchQueue.main.async(execute: {
    //Benutzeroberfläche aktualisieren
    self.tableView.reloadData()
})

Von AppCoda: https://www.appcoda.com/grand-central-dispatch/

//Dies wird synchron gedruckt, d.h. es wird 1-9 & 100-109 drucken
func simpleQueues() {
    let queue = DispatchQueue(label: "com.appcoda.myqueue")

    queue.sync {
        for i in 0..<10 {
            print("", i)
        }
    }

    for i in 100..<110 {
        print("", i)
    }
}

//Dies wird asynchron gedruckt
func simpleQueues() {
    let queue = DispatchQueue(label: "com.appcoda.myqueue")

    queue.async {
        for i in 0..<10 {
            print("", i)
        }
    }

    for i in 100..<110 {
        print("", i)
    }
}

49voto

Said Sikira Punkte 4532

Swift 3 Version

Swift 3 verwendet die neue DispatchQueue-Klasse zur Verwaltung von Warteschlangen und Threads. Um etwas im Hintergrund auszuführen, würde man Folgendes verwenden:

let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
    print("Im Hintergrundthread ausführen")
}

Oder wenn man etwas in zwei Zeilen Code haben möchte:

DispatchQueue.global(qos: .background).async {
    print("Im Hintergrundthread ausführen")

    DispatchQueue.main.async {
        print("Wir haben das fertig.")
        // nur zurück im Hauptthread, UI zugänglich:
        label.text = "Erledigt."
    }
}

Man kann auch einige detaillierte Informationen zu GDC in Swift 3 in diesem Tutorial erhalten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X