ObservableObjectとは?
ライフサイクルについて調べた
公式を翻訳したが意味がわからなかった
オブジェクトが変更される前に発行するパブリッシャーを持つオブジェクトのタイプ。
protocol ObservableObject : AnyObject
デフォルトでは、ObservableObject は @Published プロパティが変更される前に、変更された値を発行する objectWillChange パブリッシャーを合成します。
class Contact: ObservableObject {
@Published var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
cancellable = john.objectWillChange
.sink { _ in
print("\(john.age) will change")
}
print(john.haveBirthday())
// Prints "24 will change"
// Prints "25"
なので別の解説を調べた
ObservableObjectはSwiftUIの重要な部分で、データの変更を監視し、それに応じてビューを更新するために使用されるプロトコルです。SwiftUIは宣言的なフレームワークであり、ビューの状態が変わるとビューの再描画がトリガーされます。ObservableObjectを使うことで、データの変更がビューに反映されるようになります。
ObservableObjectの主要な特徴:
@Published プロパティラッパー: ObservableObjectプロトコルを実装するクラス内のプロパティに@Published属性を付与することで、そのプロパティの値が変更されたときにリスナー(ビュー)に通知します。これにより、ビューは最新のデータを反映できるようになります。
データバインディング: ObservableObjectは、ビューとモデル間のデータバインディングを容易にします。SwiftUIビューは@ObservedObjectまたは@StateObjectを使用してObservableObjectを監視し、データの変更に応じてビューを更新します。
Combineフレームワークとの統合: ObservableObjectはCombineフレームワークと密接に統合されており、データの変更を監視し、それに応じて動作するコンポーネントを作成することができます。
例:
以下は、ObservableObjectを使用する簡単な例です:
import SwiftUI
import Combine
class MyViewModel: ObservableObject {
@Published var score = 0
}
struct MyView: View {
@ObservedObject var viewModel = MyViewModel()
var body: some View {
VStack {
Text("Score: \(viewModel.score)")
Button("Increase Score") {
viewModel.score += 1
}
}
}
}
この例では、MyViewModelクラスがObservableObjectプロトコルを実装しており、scoreプロパティに@Published属性が付けられています。そのため、scoreの値が変更されると、MyViewは自動的に更新され、新しいスコアが表示されます。
ObservableObjectの使用により、SwiftUIビューの状態管理とデータフローが簡単かつ効率的になります。これはMVVM(Model-View-ViewModel)パターンをSwiftUIで実装する際に特に重要です。
感想
ObservableObjectは、データの変更を監視して、Viewに変更を通知するオブジェクトで、ViewModelとして使われているようですね。
Combineを使用してAPI通信を使用するときに、よく使われるようです。
モックサーバーと通信をするときに、データをPOSTしたとき、こんなコードを書いてみました。参考までにどうぞ。詳しくは次の記事でご紹介します。
import Combine
import Foundation
class BookViewModel: ObservableObject {
var cancellables = Set<AnyCancellable>()
func postBook(book: Book) {
guard let url = URL(string: "http://localhost:3000/bookList") else {
print("Invalid URL")
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
do {
request.httpBody = try JSONEncoder().encode(book)
} catch {
print("Failed to encode book")
return
}
URLSession.shared.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: [String: Book].self, decoder: JSONDecoder())
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
break
case .failure(let error):
print("Error: \(error)")
}
}, receiveValue: { response in
print("Success: \(response)")
})
.store(in: &cancellables)
}
}
Discussion