みなさんこんにちは!
イザナギです!
さて、今回は久しぶりの「Swift UI」に関する話題です!
だいぶ前ですが、Swift UIを使っていたときのエラーについての記事について書いていました。
Swift UIを使ってクラスを実行したらエラーが出た話
それからしばらくSwift UIは使っていなかったのですが、しばらく経って「やっぱ気になる!」と思ったので、また使って見ました!
SwiftUIについて
おさらいですが、SwiftUIとはより少ないコードでデザインを構築できるツールです。
SwiftUI概要 - Xcode - Apple Developer
以前のUIkitに比べて、比較的コードが少なく書くことができます!
利用するもの
今回利用するものは以下の通りです。
- SwiftUI
- NewsAPI
- iPad(シュミュレーター)
NewsAPIについては前回も記事で紹介しましたね!
ニュースを簡単に表示できる!「News API」をご紹介!
実装!
では、早速実装して見ましょう!
データの受け取りに「Codable」を利用する
「Codable」とは、簡単にいうとAPIなどで受け取ったデータ(JSONデータ)をSwiftで使いやすくするために、「データ型」に変換するプロトコルです。
簡単にいうと、Swiftで使いやすくするものですね!
例えば、NewsAPIで以下のようなデータを取ったとします。
{
"status": "ok",
"totalResults": 3456,
-"articles": [
-{
-"source": {
"id": null,
"name": "Cointelegraph.com"
},
"author": "Cointelegraph By Marie Huillet",
"title": "Roger Ver Apparently Unconcerned About Coronavirus",
"description": "Roger Ver, the prominent Bitcoin Cash advocate and former CEO of Bitcoin.com, appears to think that the world’s reaction to the COVID-19 pandemic is disproportionate",
"url": "https://cointelegraph.com/news/roger-ver-apparently-unconcerned-about-coronavirus",
...
},
...
}
一例として、これを構造体で表すと以下の通りになります。
struct NewsSource: Codable {
let status: String!
let totalResults: Int!
var articles: [Article]
}
struct Article: Codable{
var id: Int?
var author: String!
var title: String!
var description: String!
var publishedAt: String!
・・・
}
今回は、必要なもののみ取り出しています。
このように、まずJSONの階層ごとにデータ型を決めていきます。
今回のように、必要なデータのみを書いていても大丈夫なので、必要ないデータはCodableに入れないようにしましょう!
APIからデータを取得し、格納させる
そして、先ほど作ったCodableのなかにデータを格納していきます。
//APIを叩いてデータを取得し、構造体に格納
class GetNewsEventFetcher: ObservableObject {
@Published var articles: [Article] = []
let url: URL = URL(string:"ここにAPIキーを含んだURLを挿入")!
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
let decoder: JSONDecoder = JSONDecoder()
do {
var searchedResult = try decoder.decode(NewsSource.self, from: data)
DispatchQueue.main.async {
// データを格納
self.articles = searchedResult.articles
print(self.articles)
}
} catch {
// 何かしらのエラー処理を書く
}
}.resume()
}
クラスに「ObservableObject」をつけることで、変数などのプロパティの情報を管理できるようになります!
これがとても便利で!非同期通信で、データが取得(プロパティが更新)されると通知してくれるものです。
「ObservableObject」をつけずに、SwiftUIのViewで、普通に値を取り出そうとするとエラーになると思います。
そして、自動通知させる変数の宣言の前に「@Published」をつけると、値が変更された時に、通知されるようになります。
Viewの実装
ここで、SwiftUIによるView画面を実装していきます。
今回はあまりデザインを気にせずに、ただ表示だけを行っています。
struct ContentView: View {
//
@ObservedObject var store = GetNewsEventFetcher()
var body: some View{
// リスト表示(idはdescription(記事の内容)を使用)
List(self.store.articles, id: \.description){ res in
VStack(alignment: .leading){
// 記事の表示
Text(res.author)
Text(res.title)
Text(res.description)
Text(res.publishedAt)
}
// 余白を開ける
.padding()
}
}
}
「@ObservedObject var store = GetNewsEventFetcher()」の部分が、通知を受け取っています。
「@ObservedObject」をつけないと、通知を受け取れませんのでご注意を!
詰まったところ
SwiftUIの「List」で値を表示する時に、「id」を指定していなかったので、表示されるものが一種類だけになった。
よく、NewsAPIのJSON値を見てみるとidがないではないか!
でも「List」を使って表示するときは、ユニークなidが必要になるらしい。
なので、今回は記事の内容はかぶらないと思い「description」を採用させてもらいました。
まあ、IDをつけた方がいいとは思うのだけれど、今回は表示だけなので実装はしていないです。
完成!
完成するとこのようになると思います。
これは、キーワードを「気仙沼」にしたときのものです。
ちゃんと表示できてますね!
あとは、デザインのみ!
まとめ
今回はSwiftUIでニュースを表示させて見ました。
初めは、Codableを理解するのにちょっと苦しみました。
でも、慣れればなんとかなるもんですね!www
まだ理解できてない部分もあるので、これからも学習に励んでいきたいと思います!
それでは、今回はここで筆を置かせていただきます!
最後まで記事をご覧頂きありがとうございました!