SwiftUIのViewを更新するためにはデータに応じて、適切な状態の宣言をする必要があります。
ここでは、Web APIと通信し結果を表示するという、よくあるアプリをSwiftUIで実装することで、その方法を紹介します。
必要な実装は以下の2つです。
-
ObservableObject
に準拠するクラスを作成し変更の通知を発行 - SwiftUIのViewで通知を監視
それでは、GitHubのフォローしているユーザー一覧を表示するアプリを例にし、実装していきます。
ObservableObjectに準拠するクラスを作成し変更の通知を発行
通信を行い取得したユーザーを保持するクラスを作成し、ObservableObject
に準拠させます。(準拠させると言ってもクラスであれば特に何かを実装する必要は無いです)
そして、保持したユーザーの変更を通知するためには、 @Published
属性をプロパティに付与します。
import Foundation
import Combine
class FollowingUserStore: ObservableObject {
@Published var users: [User] = []
init() {
load()
}
func load() {
let url = URL(string: "https://api.github.com/users/maoyama/following")!
URLSession.shared.dataTask(with: url) { data, response, error in
DispatchQueue.main.async {
self.users = try! JSONDecoder().decode([User].self, from: data!)
}
}.resume()
}
}
struct User: Decodable, Identifiable {
var id: Int
var login: String
}
たったこれだけの実装で、通信を行いユーザーを取得できた際の通知を発行することが可能になります。
SwiftUIのViewで通知を監視
今回のような、あるViewだけで使用するデータの通知を監視すれば良い場合はProperty WrapperのObservedObject
を使う方法が適切です。
ObservableObject
をプロパティに保持し、@ObservedObject
を付与します。
import SwiftUI
struct ContentView: View {
@ObservedObject var store = FollowingUserStore()
var body: some View {
List(store.users) { (user) in
UserRow(user: user)
}
}
}
struct UserRow: View {
var user: User
var body: some View {
Text(user.login)
}
}
これで FollowingUserStore.users
の変更を監視できます。
まとめ
これだけの実装でWeb APIから取得した結果を表示することができました。
また、適切な宣言をするだけで、データの同期を手動ですることなく、SwiftUIとCombineが自動で行ってくれています。これにより、コードがとてもシンプルで読みやすくなることが期待できそうです。
参考資料
https://developer.apple.com/documentation/swiftui/state_and_data_flow
https://developer.apple.com/videos/play/wwdc2019/226/
https://developer.apple.com/documentation/combine/observableobject