[SWIFT] URLSession mit URLSession und Normal kombinieren

Überblick

Ich habe untersucht, wie man URLSession normal schreibt und wie man in Combine schreibt.

Gegenstand

Wir werden die LGTM-Akquisitions-API von Qiita als Beispiel verwenden. Referenz: LGTM und Ansicht Ihres Artikels mit der Qiita-API abrufen. --Qiita

Derzeit erhält LGTM ungefähr 5 Artikel LGTM.

https://qiita.com/api/v2/items/a9ead7285d10aadf5643/likes

Sie können es erhalten, indem Sie diese URL mit GET treffen.

Gewöhnliche URLSession

import Foundation

let qiitaURL = URL(string: "https://qiita.com/api/v2/items/a9ead7285d10aadf5643/likes")!

struct LGTM: Codable {
    var created_at: String
    var user: User
}
struct User: Codable {
    var id: String
}

let session = URLSession.shared.dataTask(with: qiitaURL) {data, response, error in
    if let error = error {
        fatalError("Error: \(error.localizedDescription)")
    }
    guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
        fatalError("Error: invalid HTTP response code")
    }
    guard let data = data else {
        fatalError("Error: missing response data")
    }

    do {
        let lgtms = try JSONDecoder().decode([LGTM].self, from: data)
        lgtms.forEach{ lgtm in
            print("username: \(lgtm.user.id), created_at \(lgtm.created_at)")
        }
    }
    catch {
        print("Error: \(error.localizedDescription)")
    }
}
session.resume()

Der Typ von "let session" ist "URLSessionDataTask". Kommunizieren Sie, indem Sie den Lebenslauf von "URLSessionDataTask" aufrufen.

Die Definition der URLSession-Methode dataTask lautet wie folgt.


open func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask

URLSession mit Kombinieren

Die Beschreibung in Kombinieren lautet wie folgt.

import Foundation
import Combine

var cancellable = URLSession.shared
    .dataTaskPublisher(for: qiitaURL)
    .tryMap { element -> Data in
        guard let httpResponse = element.response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
            throw URLError(.badServerResponse)
        }
        return element.data
    }
    .decode(type: [LGTM].self, decoder: JSONDecoder())
    .sink(receiveCompletion: {
        print("complete! \($0)")
    }, receiveValue: { lgtms in
        lgtms.forEach{ lgtm in
            print("username: \(lgtm.user.id), created_at \(lgtm.created_at)")
        }
    })

Die Verarbeitung hat sich ein wenig geändert, aber ich bin der Meinung, dass Combine im CompletionHandler weniger Verarbeitung hat und die Aussichten besser sind.

Tips

Geben Sie einen Namen an, von dem Sie nicht wissen, ob es sich um JsonDecoder handelt oder nicht.

Wenn Sie etwas angeben, das nicht im Json-Feldnamen enthalten ist, "Fehler: Die Daten konnten nicht gelesen werden, weil sie fehlen." Und Json Decoder gibt einen Fehler aus.

Zum Beispiel, wenn struct wie folgt definiert ist.

struct User: Codable {
    var id: String
    var aaa: String
}

In einem solchen Fall ist es möglich, einen Fehler durch Eingabe von "nil" zu verhindern, indem der möglicherweise nicht vorhandene Feldname auf "Optional" gesetzt wird.

struct User: Codable {
    var id: String
    var aaa: String?
}

Was ist URLSession.shared?

URLSession.shared ist ein Singleton, den Sie verwenden können, wenn Sie schnell schreiben möchten. Da es mit dem Standardverhalten funktioniert, kann keine erweiterte Verarbeitung durchgeführt werden.

shared | Apple Developer Documentation

Was ist Element-> Daten?

Es gibt nur das Abschlussargument an. Es funktioniert auch dann, wenn kein -> Data Teil vorhanden ist.

Closures — The Swift Programming Language (Swift 5.3)

Ich möchte die Elemente eines Arrays einzeln verarbeiten

In Combine wird der URLSession-Abonnementprozess derzeit von forEach verschachtelt.

.decode(type: [LGTM].self, decoder: JSONDecoder())
.sink(receiveValue: { lgtms in
        lgtms.forEach{ lgtm in
            print("username: \(lgtm.user.id), created_at \(lgtm.created_at)")
        }
    }

Sie können "flatMap" verwenden, um diese Verschachtelung zu entfernen.

.decode(type: [LGTM].self, decoder: JSONDecoder())
.flatMap {$0.publisher}
.sink(receiveCompletion: {
    print("complete! \($0)")
}, receiveValue: { lgtm in
    print("username: \(lgtm.user.id), created_at \(lgtm.created_at)")
})

das Ende

Recommended Posts

URLSession mit URLSession und Normal kombinieren
[macOS] Zielaktion mit Kombinieren verarbeiten
Verwenden Sie Java mit MSYS und Cygwin
Verteilte Ablaufverfolgung mit OpenCensus und Java
Installieren Sie Java und Tomcat mit Ansible
Punkt 32: Kombinieren Sie Generika und Varargs mit Bedacht
Verwenden von Git mit SourceTree und Eclipse
Verwenden Sie JDBC mit Java und Scala.
Hallo Welt mit Kotlin und JavaFX
Hallo Welt mit Docker und C Sprache
Verarbeitungsgeschwindigkeit mit und ohne statische Aufladung
PDF und TIFF mit Java 8 ausgeben
Datenverknüpfung mit Spark und Cassandra
Ziehen Sie Dateien mit JavaFX per Drag & Drop
Kopieren Sie den Test und fügen Sie ihn mit RSpec ein
Schieberegler mit GWT und Smart GWT anzeigen
Hallo Welt mit GWT 2.8.2 und Maven
Microservices mit Docker- und Cloud-Leistung
Mit Java verschlüsseln und mit C # entschlüsseln
Mit Jackson gut formen und serialisieren