J'ai étudié comment écrire URLSession normalement et comment écrire dans Combine.
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.
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
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
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?
}
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
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)
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)")
})
Recommended Posts