見出し画像

SwiftUIでいこう! - CombineでURLSession。

URLSessionの通常の書き方とCombineでの書き方が比較してあります

CombineでdataTaskPublisherを使いJsonのデータを取得しています。サイトのコードをそのまま実行してみます。

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

実行すると、

username: h1d3mun3, created_at 2020-12-16T17:27:07+09:00
username: st43, created_at 2020-09-25T09:52:25+09:00
username: yo-okazawa, created_at 2020-09-23T12:22:08+09:00
username: LittleWat, created_at 2020-09-23T11:36:11+09:00
username: funnything, created_at 2020-09-23T10:35:44+09:00
username: shigeshige0914, created_at 2020-09-23T07:47:35+09:00

Jsonデータを指定URLより一部を取り出すと、

[
 {
   "created_at": "2020-12-16T17:27:07+09:00",
   "user": {
     "description": "iOS App Developer / Swift / RxSwift",
     "facebook_id": "",
     "followees_count": 9,
     "followers_count": 11,
     "github_login_name": null,
     "id": "h1d3mun3",
     "items_count": 8,
     "linkedin_id": "",
     "location": "Tokyo, Japan",
     "name": "Hidemune Takahashi",
     "organization": "",
     "permanent_id": 203170,
     "profile_image_url": "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203170/profile-images/1606447281",
     "team_only": false,
     "twitter_screen_name": null,
     "website_url": ""
   }
 },

となっていて、"user" の"id"と"created_at"データが取り出されいるのが分かります。

Combineでも同じことをすると、

import Foundation
import Combine

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

これを実行すると、

username: h1d3mun3, created_at 2020-12-16T17:27:07+09:00
username: st43, created_at 2020-09-25T09:52:25+09:00
username: yo-okazawa, created_at 2020-09-23T12:22:08+09:00
username: LittleWat, created_at 2020-09-23T11:36:11+09:00
username: funnything, created_at 2020-09-23T10:35:44+09:00
username: shigeshige0914, created_at 2020-09-23T07:47:35+09:00
complete! finished

同じように、"user" の"id"と"created_at"データが取り出されいるのが分かります。

Json形式のデータを取得します。Jsonデータとしては大項目としては

"created"、"user"

この2つ。そして、"user"の中にデータがたくさんあリますが、"id"を取り出すように Codableに準拠したstructを作っています。

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

そして、

var user: User

の部分はさらにstructをつくります。

struct User: Codable {
   var id: String
}

これでデータの読み込み準備ができました。

URLSessionを使ってデータを読み込みdataTask、または、dataTaskPublisherを使ってデータ処理します。dataTaskPublisherは完結に書くことができます。

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

の部分でデータを受けJsonをパース、使える状態とします。そして、使い方は".sink"以下

.sink(receiveCompletion: {
print("complete! \($0)")
}, receiveValue: { lgtms in
lgtms.forEach{ lgtm in
print("username: \(lgtm.user.id), created_at \(lgtm.created_at)")
}

これでデータを取り出すことができます。以下参考サイトです。


この記事が気に入ったらサポートをしてみませんか?