Background-Thread in Swift: Leitfaden für Anfänger und Profis

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum Hintergrund-Threads der Schmerz eines jeden iOS-Entwicklers sind?

\n\n

Stellen Sie sich vor: Sie schreiben eine App zum Herunterladen von Fotos aus dem Internet. Alles funktioniert perfekt... bis der Benutzer auf die Schaltfläche "Herunterladen" klickt. Der Bildschirm friert ein, die App "ruckelt", und nach ein paar Sekunden beendet iOS einfach Ihren Prozess. Kommt Ihnen das bekannt vor?

\n\n

Das Problem ist, dass alle Operationen standardmäßig auf dem Hauptthread (main thread) ausgeführt werden. Der Hauptthread ist aber für die Darstellung der UI zuständig – wenn Sie ihn mit einer langen Aufgabe blockieren, reagiert die Oberfläche nicht mehr auf Berührungen. Die Lösung? Verwenden Sie einen Background-Thread (Hintergrundthread) in Swift.

\n\n

In diesem Artikel werden wir anhand praktischer Beispiele durchgehen, wie man mit Hintergrund-Threads arbeitet. Sie erfahren mehr über GCD, OperationQueue und das neue async/await aus Swift 5.5+. Los geht's!

\n\n

Was ist ein Thread in Swift?

\n\n

Ein Thread ist ein leichter Prozess, der den Code eines Programms ausführt. Eine iOS-App hat einen Hauptthread (main thread) und viele Hintergrund-Threads. Der Hauptthread kümmert sich um die UI: Er aktualisiert den Bildschirm, verarbeitet Gesten und Animationen. Alles, was die Oberfläche betrifft, sollte nur auf dem Hauptthread stattfinden.

\n\n

Hintergrund-Threads (background threads) werden benötigt für:

\n
    \n
  • Herunterladen von Daten aus dem Netzwerk
  • \n
  • Arbeiten mit Dateien (Lesen/Schreiben)
  • \n
  • Komplexe Berechnungen (Bildverarbeitung, Verschlüsselung)
  • \n
  • Arbeiten mit Datenbanken
  • \n
\n\n

Wenn Sie versuchen, die UI von einem Hintergrund-Thread aus zu aktualisieren, stürzt die App entweder mit einem Fehler ab, oder Sie sehen ein seltsames Verhalten der Oberfläche.

\n\n

GCD (Grand Central Dispatch) – die klassische Methode

\n\n

Grand Central Dispatch (GCD) ist eine Low-Level-Bibliothek zur Thread-Verwaltung, die in iOS/macOS integriert ist. Sie arbeitet über Warteschlangen (queues): Sie legen eine Aufgabe in die Warteschlange, und das System entscheidet selbst, auf welchem Thread sie ausgeführt wird.

\n\n

DispatchQueue.main – der Hauptthread

\n

Wenn Sie Code auf dem Hauptthread ausführen müssen (z. B. ein UILabel aktualisieren), verwenden Sie:

\n\n
DispatchQueue.main.async {\n    self.label.text = "Download abgeschlossen!"\n}
\n\n

DispatchQueue.global() – der Hintergrund-Thread

\n

Für Hintergrundaufgaben verwenden Sie die globale Warteschlange:

\n\n
DispatchQueue.global(qos: .background).async {\n    // Schwere Arbeit\n    let imageData = try? Data(contentsOf: url)\n    \n    // Zurück zum Hauptthread für die UI\n    DispatchQueue.main.async {\n        self.imageView.image = UIImage(data: imageData!)\n    }\n}
\n\n

Der Parameter qos (Quality of Service) bestimmt die Priorität der Aufgabe:

\n
    \n
  • .userInteractive – die höchste Priorität, für UI
  • \n
  • .userInitiated – der Benutzer wartet auf das Ergebnis
  • \n
  • .utility – langwierige Aufgaben (Dateidownloads)
  • \n
  • .background – niedrige Priorität (Synchronisation, Backups)
  • \n
\n\n

OperationQueue – mehr Kontrolle

\n\n

OperationQueue ist ein Aufsatz auf GCD mit zusätzlichen Funktionen:

\n
    \n
  • Abbrechen von Aufgaben
  • \n
  • Abhängigkeiten zwischen Aufgaben
  • \n
  • Maximale Anzahl paralleler Threads
  • \n
\n\n

Beispiel für das Herunterladen mehrerer Bilder:

\n\n
let queue = OperationQueue()\nqueue.maxConcurrentOperationCount = 2 // Nicht mehr als 2 Aufgaben gleichzeitig\n\nlet operation1 = BlockOperation {\n    // Erstes Bild herunterladen\n    sleep(2)\n    print("Foto 1 heruntergeladen")\n}\n\nlet operation2 = BlockOperation {\n    // Zweites Bild herunterladen\n    sleep(3)\n    print("Foto 2 heruntergeladen")\n}\n\n// operation2 beginnt erst nach Abschluss von operation1\noperation2.addDependency(operation1)\n\nqueue.addOperations([operation1, operation2], waitUntilFinished: false)
\n\n

Dies ist praktisch, wenn Aufgaben in einer strengen Reihenfolge oder mit Ressourcenbeschränkungen ausgeführt werden müssen.

\n\n

Modernes async/await (Swift 5.5+)

\n\n

Seit Swift 5.5 bietet Ap

Blogs

Buchempfehlungen