🪶
SwiftUI Observation
Observation
Make responsive apps that update the presentation when underlying data changes.
観察
基礎となるデータが変更されたときにプレゼンテーションが更新されるレスポンシブ・アプリを作成する。
日本語の字幕付きで公式を見ていただいた方が良いと思う。
Observationは、プロパティの変更を追跡するためのSwiftの新機能です。と解説されている。マクロのマジックで動作するらしい?
モデルを定義するときに、型を自動で生成してくれるとか?
Honoと呼ばるFWで作成したREST APIからデータをHTTP GETする例で使い方を解説します。
structでモデルを作成する。
import Foundation
struct Product: Identifiable, Codable {
let id: String
let name: String
let description: String
}
Combineで作ったコードと比較してもそこまで変わらない気がするが、APIからデータを取得するコードを簡潔に、書けている気がする。
import SwiftUI
import Observation
@Observable
class ProductManager {
var products: [Product] = []
var isLoading = false
var errorMessage: String?
func fetchProducts() {
isLoading = true
errorMessage = nil
guard let url = URL(string: "https://hono-shop-app.gitonly543.workers.dev/api/shop") else {
errorMessage = "Invalid URL"
isLoading = false
return
}
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
DispatchQueue.main.async {
self?.isLoading = false
if let error = error {
self?.errorMessage = error.localizedDescription
return
}
guard let data = data else {
self?.errorMessage = "No data received"
return
}
do {
let decodedProducts = try JSONDecoder().decode([Product].self, from: data)
self?.products = decodedProducts
} catch {
self?.errorMessage = "Failed to decode data: \(error.localizedDescription)"
}
}
}.resume()
}
}
Viewに表示するときは、ObservableObjectを使わなかった。いつもなら、ViewModelのようなクラスを作って、やってるのだが、裏側でそんな機能を作ってくれているのか???
import SwiftUI
struct ContentView: View {
@State private var productManager = ProductManager()
var body: some View {
NavigationStack {
Group {
if productManager.isLoading {
ProgressView()
} else if let errorMessage = productManager.errorMessage {
Text(errorMessage)
.foregroundColor(.red)
} else {
List(productManager.products) { product in
VStack(alignment: .leading) {
Text(product.name)
.font(.headline)
Text(product.description)
.font(.subheadline)
.foregroundColor(.secondary)
}
}
}
}
.navigationTitle("Products")
}
.onAppear {
productManager.fetchProducts()
}
}
}
#Preview {
ContentView()
}
プレビューで確認するとこんな感じで、APIからデータを取得して表示できます。
感想
複雑な処理を書かずともコードを書けているように感じた。Combineだともっと多くの処理を書いていた気がする。View状態が変更されるロジックを書くなら、Observationを使うと良いかもしれない。
私の場合は、いつもObservableObject
を使ったクラスを使っていますね。
Discussion