Einleitung
Moderne iOS- und macOS-Anwendungen kommen selten ohne Interaktion mit entfernten Servern aus. Ob das Laden von Daten aus einem Newsfeed, das Senden eines Registrierungsformulars oder die Synchronisation von Dateien – all diese Vorgänge erfordern eine saubere Implementierung eines HTTP-Clients. Im Swift-Ökosystem steht Entwicklern das leistungsstarke integrierte Framework URLSession zur Verfügung, das durch die Einführung von async/await von Jahr zu Jahr komfortabler wird.
In diesem Artikel werden wir uns ansehen, wie man HTTP-Anfragen in Swift richtig erstellt, angefangen bei grundlegenden Strukturen bis hin zu fortgeschrittenen Techniken der Fehlerbehandlung und Datenserialisierung. Sie erfahren, wie Sie sauberen, sicheren und leistungsstarken Netzwerkcode für Ihre Anwendungen schreiben.
Grundlagen von URLSession: Die erste HTTP-Anfrage
Die Klasse URLSession ist die Grundlage für jede Netzwerkarbeit in Swift. Sie verwaltet Konfiguration, Caching, Sitzungen und die direkte Ausführung von Anfragen. Betrachten wir eine einfache GET-Anfrage zum Abrufen von Daten von einem Server.
Erstellen einer einfachen GET-Anfrage
import Foundation
// 1. URL erstellenguard let url = URL(string: "https://api.example.com/users") else { print("Ungültige URL") return}
// 2. Anfrage erstellen (standardmäßig GET)var request = URLRequest(url: url)request.httpMethod = "GET"request.setValue("application/json", forHTTPHeaderField: "Accept")
// 3. Sitzung erstellenlet session = URLSession.shared
// 4. Anfrage ausführen (alte Methode mit Closure)let task = session.dataTask(with: request) { data, response, error in if let error = error { print("Anfragefehler: \\(error.localizedDescription)") return } guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { print("Server hat einen Fehler zurückgegeben") return } if let data = data, let jsonString = String(data: data, encoding: .utf8) { print("Empfangene Daten: \\(jsonString)") }}task.resume() // Wichtig! Aufgabe startenWichtige Punkte: Überprüfen Sie immer den Antwortstatus (200...299), vergessen Sie nicht, resume() aufzurufen, und behandeln Sie mögliche Fehler. In realen Projekten wird dieser Code normalerweise in eine separate Dienstschicht ausgelagert.
Moderner Ansatz: async/await
Seit Swift 5.5 gibt es die Möglichkeit, async/await zu verwenden, was den Code wesentlich lesbarer macht und die „Pyramide der Closures“ vermeidet.
func fetchUsers() async throws -> Data { guard let url = URL(string: "https://api.example.com/users") else { throw URLError(.badURL) } var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Accept") let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw URLError(.badServerResponse) } return data}Dieser Code kann von jeder asynchronen Funktion oder Aufgabe aus aufgerufen werden, was die Logik erheblich vereinfacht.
Arbeit mit JSON: Codable und Datenmodelle
Selten kommen Daten in „roher“ Form an. Meistens haben wir es mit JSON zu tun. Swift bietet eine elegante Lösung – das Protokoll Codable (das Encodable und Decodable vereint).
Erstellen eines Modells und Dekodieren
// 1. Datenstruktur definierenstruct User: Codable { let id: Int let name: String let email: String}
// 2. Asynchrone Funktion zum Abrufen eines Benutzerarraysfunc fetchUsers() async throws -> [User] { let data = try await fetchUsersData() // aus dem vorherigen Beispiel let decoder = JSONDecoder() return try decoder.decode