「SwiftUI」でニュースを表示して見た!

みなさんこんにちは!
イザナギです!
さて、今回は久しぶりの「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
まだ理解できてない部分もあるので、これからも学習に励んでいきたいと思います!
それでは、今回はここで筆を置かせていただきます!
最後まで記事をご覧頂きありがとうございました!

■関連記事(精度そんな良くないかもwww)

■関連トピック

2024 - Izanagi's Site