[SWIFT] URLSession avec URLSession et Combine normalement

Aperçu

J'ai étudié comment écrire URLSession normalement et comment écrire dans Combine.

Matière

Nous utiliserons l'API d'acquisition LGTM de Qiita comme exemple. Référence: Obtenez LGTM et consultez votre article avec l'API Qiita. --Qiita

Actuellement, LGTM reçoit environ 5 articles LGTM.

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

Vous pouvez l'obtenir en cliquant sur cette URL avec GET.

URLSession ordinaire

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()

Le type de let session est ʻURLSessionDataTask. ʻCommuniquez en appelant CV de URLSessionDataTask.

La définition de la méthode URLSession dataTask est la suivante.


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

URLSession avec Combine

La description dans Combine est la suivante.

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)")
        }
    })

Le traitement a un peu changé, mais je pense que Combine a moins de traitement dans le completionHandler et les perspectives sont meilleures.

Tips

Spécifiez un nom dont vous ne savez pas s'il s'agit de JsonDecoder ou non.

Si vous spécifiez quelque chose qui ne figure pas dans le nom du champ Json, ʻError: Les données n'ont pas pu être lues car elles sont manquantes .` et JsonDecoder donne une erreur.

Par exemple, lorsque la structure est définie comme suit.

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

Dans un tel cas, il est possible d'éviter une erreur en entrant «nil» en définissant le nom de champ qui peut ne pas exister sur Facultatif.

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

Qu'est-ce que URLSession.shared?

URLSession.shared est un singleton à utiliser lorsque vous souhaitez écrire rapidement. Comme il fonctionne avec le comportement par défaut, le traitement avancé ne peut pas être effectué.

shared | Apple Developer Documentation

Qu'est-ce que element-> Data?

Il spécifie simplement l'argument de fermeture. Cela fonctionne même s'il n'y a pas de partie -> Data.

Closures — The Swift Programming Language (Swift 5.3)

Je souhaite traiter les éléments d'un tableau un par un

Dans Combine, le processus d'abonnement URLSession est actuellement imbriqué par forEach.

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

Vous pouvez utiliser flatMap pour vous débarrasser de cette imbrication.

.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)")
})

la fin

Recommended Posts

URLSession avec URLSession et Combine normalement
[macOS] Traiter l'action cible avec la combinaison
Utiliser java avec MSYS et Cygwin
Traçage distribué avec OpenCensus et Java
Installez Java et Tomcat avec Ansible
Point 32: Combiner judicieusement les génériques et les varargs
Utiliser Git avec SourceTree et Eclipse
Utilisez JDBC avec Java et Scala.
Bonjour tout le monde avec Kotlin et JavaFX
Hello World avec Docker et langage C
Vitesse de traitement avec et sans statique
Sortie PDF et TIFF avec Java 8
Liaison de données avec Spark et Cassandra
Faites glisser et déposez des fichiers avec JavaFX
Copier et coller le test avec RSpec
Afficher le curseur avec GWT et Smart GWT
Hello World avec GWT 2.8.2 et Maven
Microservices avec Docker et Cloud Performance
Crypter avec Java et décrypter avec C #
Formez et sérialisez bien avec Jackson