猫でもわかるWebプログラミングと副業

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

APIリクエスト結果をUIに反映させる - Swift UI チュートリアル Part 5

f:id:yoshiki_utakata:20191225120619p:plain

やること

新年あけましておめでとうございます。

新年なので、非同期でAPIリクエストを行い、結果がかえってき次第リスト形式でUIに表示させたいです。

重要なこと

Swift UI は、Vue.js と同じように

  • UI部分
  • データ(ステート)を持つ部分
  • 普通のプログラム部分

があり、

  • プログラムを実行する
  • データが変わる
  • UIに反映される

という流れで処理を行います。

実装するべきもの

  • データを持つ部分
  • UIを表示する部分
  • APIからデータをとってきて「データを持つやつ」に渡してやる

ちなみに

今回はこの Swift UI チュートリアルを参考にしました。

Handling User Input

https://developer.apple.com/tutorials/swiftui/handling-user-input

データを持つ部分の実装

データを持つ部分の前に、今回は「音楽」のデータをAPIからとってこようと思うので、音楽のstructを定義します。

struct Audio {
    let id: String
    let title: String
}

データを持つ部分を実装します。

import SwiftUI
import Combine

final class AudioData: ObservableObject {
    @Published var audios: [Audio] = []
}
  • import SwiftUI しているのは @Published のため
  • import Combine しているのは ObservableObject のため、のはず。。。

@Published が指定されていると、この変数の状態が変わるとUIを再描画しなきゃいけないよ、的なことを表しているんだと思う。

Observable を継承しておく必要があります。

UIの実装

Listの要素一つ

import SwiftUI

struct AudioRow: View {
    let audio: Audio
    
    var body: some View {
        HStack {
            Text(audio.title)
            Spacer()
            Text(audio.id)
        }
    }
}

List全体のUI

struct AudioList: View {
    @EnvironmentObject var audioData: AudioData
    
    var body: some View {
        NavigationView {
            List(self.audioData.audios, id: \.id) { audio in
                NavigationLink(destination: ContentView()) {
                    AudioRow(audio: audio)
                }
            }
        }
    }
}

@EnvironmentObject で先程のDataをもたせてあげて、Viewは audioDataaudios をリスト表示してやる。

APIを叩く部分

// audioData を用意して audioList に突っ込んでおく
let audioData = AudioData()
let audioList = AudioList().environmentObject(audioData)

// UIを表示させる
if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: audioList)
    self.window = window
    window.makeKeyAndVisible()
}

// URLSession はHTTPリクエストを送るやつです。
// URLSession の使い方はぐぐってください
URLSession.shared.dataTask(...){ (data, response, error) in
    // ここでAPIのレスポンスをなんだかんだ処理して

    // audioData にデータを突っ込むことで勝手にUIが更新される
    // 非同期処理の中でのUI更新になるので、
    // DispatchQueue.main を使ってメインスレッドで処理させる必要がある
    DispatchQueue.main.async {
        audioData.audios = audios
    }

}

こんな感じでデータがリストで表示されたと思います。