やること
新年あけましておめでとうございます。
新年なので、非同期で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は audioData
の audios
をリスト表示してやる。
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 } }
こんな感じでデータがリストで表示されたと思います。