Listings Sillmann/Swift-Tutorial, Teil 3

Listing 1: Download-Funktion mit Completion Handler

func downloadPhoto(name: String, completion: @escaping (Data) -> Void) {
    // Download photo with name ...
    let photoData = // Downloaded photo data
    completion(photoData)
}

--

Listing 2: Funktion für den Download deklarieren
func downloadPhoto(name: String) async -> Data {
    await withCheckedContinuation({ continuation in
        downloadPhoto(name: name) { data in
            continuation.resume(returning: data)
        }
    })
}

--

Listing 3: Completion Handler ergänzen
func downloadPhoto(name: String, completion: @escaping (Data?, Error?) -> Void) {
    // Download photo with name ...
    if photoDownloadFailed {
        completion(nil, downloadError)
    } else {
        completion(photoData, nil)
    }
}

--

Listing 4: async-Variante mit verändertem Rückgabtyp
func downloadPhoto(name: String) async -> Data? {
    await withCheckedContinuation({ continuation in
        downloadPhoto(name: name) { data, error in
            guard data != nil, error == nil else {
                continuation.resume(returning: nil)
            }
            continuation.resume(returning: data!)
        }
    })
}

--

Listing 5: Die Funktion downloadPhoto(name:) mit Error Handling
func downloadPhoto(name: String) async throws -> Data {
    try await withCheckedThrowingContinuation({ continuation in
        downloadPhoto(name: name) { data, error in
            guard data != nil, error == nil else {
                continuation.resume(throwing: PhotoDownloadError.downloadFailed)
                return
            }
            continuation.resume(returning: data!)
        }
    })
}

--

Listing 6: Ausgangsimplementierung und Variation mit async
// Ursprüngliche Methode
func downloadPhoto(name: String, completion: @escaping (Data?, Error?) -> Void) {
    // Download photo with name ...
    if photoDownloadFailed {
        completion(nil, downloadError)
    } else {
        completion(photoData, nil)
    }
}

// async-Variante
func downloadPhoto(name: String) async throws -> Data {
    // Download photo with name ...
    if photoDownloadFailed {
        throw PhotoDownloadError.downloadFailed
    } else {
        return photoData
    }
}

--

Listing 7: Completion Handler aufrufen
func downloadPhoto(name: String, completion: @escaping (Data?, Error?) -> Void) {
    Task {
        do {
            let photoData = try await downloadPhoto(name: name)
            completion(photoData, nil)
        } catch {
            completion(nil, downloadError)
        }
    }
}
