こんにちは、個人開発をしているyouWoWです!
今日は、SwiftUIでデータフローを理解するために重要な2つのプロパティラッパー、@ObservableObjectと@ObservedObjectの違いについて解説します。
Observable = 観測可能
Observed = 観測される
ObservableとObservedは、プログラミングにおけるデータの変更を監視するためのパターンである「Observerパターン」に関連する用語です。
- Observable(観測可能な): このオブジェクトは、他のオブジェクトに変更を通知できるオブジェクトです。Observableは、状態が変わったことを通知する責任があります。通常、オブジェクトはリスナーやサブスクライバーを登録するためのメソッド(例えば、
addObserverやsubscribe)を提供します。 - Observed(観測される): このオブジェクトは、Observableオブジェクトからの通知を受け取り、状態が変更されたときに何らかのアクションを実行するオブジェクトです。Observedオブジェクトは、観察対象のオブジェクトに対して登録され、通知を受け取ることができます。
Observerパターンは、あるオブジェクトの状態が変化したときに、他のオブジェクトにその変化を通知するために使用されます。これにより、状態が変わったことに関心があるオブジェクト(Observedオブジェクト)が、状態が変わったときに適切なアクションを実行できます。
SwiftUIでは、ObservableObjectプロトコルと@ObservedObjectプロパティラッパーを使って、Observerパターンを実装します。ObservableObjectプロトコルを適用したオブジェクトは、状態の変更を通知できるオブジェクトで、@ObservedObjectプロパティラッパーは、Observableオブジェクトの状態が変更されたときにUIの更新をトリガーします。
公式ドキュメントへのリンクも貼り付けながら、どのように使い分けるかを具体的に説明していきます。
公式ドキュメントは以下のリンクから参照できます。
- ObservableObject – SwiftUI | Apple Developer Documentation
- ObservedObject – SwiftUI | Apple Developer Documentation
SwiftUIは、データの変更を監視してビューを自動的に更新する強力なデータバインディング機能を持っています。この記事では、@ObservableObjectと@ObservedObjectという2つの重要なプロパティラッパーの違いを解説し、それぞれの使用方法と適切なケースについて説明します。これらの概念を理解することで、データフローを効率化し、アプリ開発をスムーズに進めることができます。
@ObservableObject
@ObservableObjectは、SwiftUIフレームワークでデータの変更を監視するためのプロトコルです。データの変更が発生すると、関連するビューが自動的に更新されます。このプロトコルを適用するには、以下のように宣言します。
import SwiftUI
import Combine
class UserData: ObservableObject {
@Published var username: String = ""
@Published var age: Int = 0
}
公式ドキュメント: ObservableObject
@ObservedObject
@ObservedObjectは、プロパティラッパーであり、@ObservableObjectプロトコルに準拠したオブジェクトを監視します。ビューにこのオブジェクトをバインドすると、オブジェクトのデータが変更されたときにビューが自動的に更新されます。例えば、以下のように使用します。
import SwiftUI
struct ContentView: View {
@ObservedObject var userData: UserData
var body: some View {
VStack {
TextField("Username", text: $userData.username)
Stepper("Age: \(userData.age)", value: $userData.age)
}
}
}
公式ドキュメント: ObservedObject
@ObservableObjectと@ObservedObjectの違い
@ObservableObjectと@ObservedObjectの主な違いは、役割と使用方法です。@ObservableObjectは、データの変更を監視するオブジェクトのプロトコルを定義するために使用されます。一方、@ObservedObjectは、ビューが@ObservableObjectプロトコルに準拠したオブジェクトを監視できるようにするプロパティラッパーです。
簡単に言うと、データを提供するオブジェクトには@ObservableObjectを使用し、そのデータを監視して表示する
ビューには@ObservedObjectを使用します。これにより、データが変更されるたびにビューが自動的に更新されます。
以下に、@ObservableObjectと@ObservedObjectの使い方を示す簡単な例を示します。
import Combine
import SwiftUI
// ViewModelで@ObservableObjectを使用
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
// Viewで@ObservedObjectを使用してViewModelを監視
struct CounterView: View {
@ObservedObject var viewModel: CounterViewModel
var body: some View {
VStack {
Text("Count: \(viewModel.count)")
Button(action: viewModel.increment) {
Text("Increment")
}
}
}
}
この例では、CounterViewModelが@ObservableObjectプロトコルに準拠しており、countプロパティが@Published属性を持っているため、その値が変更されるたびに関連するビューが更新されます。CounterViewでは、@ObservedObjectを使用してCounterViewModelのインスタンスを監視しています。このため、countプロパティの値が変更されるたびに、CounterViewが自動的に更新されます。
広告
使い分け方
@ObservableObjectは、データの状態管理や変更を監視する役割があります。一方、@ObservedObjectは、ObservableObjectに準拠したオブジェクトを監視し、変更があった場合にビューを更新する役割があります。
データの共有や状態管理が必要になる場合、以下のように使い分けます。
- データモデルまたは状態管理クラスに
@ObservableObjectプロトコルを適用します。このクラスでは、@Publishedプロパティラッパーを使って監視対象のプロパティを宣言します。 - ビューでは、
@ObservedObjectプロパティラッパーを使って、ObservableObjectに準拠したオブジェクトを監視します。これにより、データモデルの変更があった場合にビューが自動的に更新されます。
以下は、@ObservableObjectと@ObservedObjectを使った実例です。
import SwiftUI
import Combine
// 1. @ObservableObjectを適用したデータモデル
class UserData: ObservableObject {
@Published var name = ""
}
struct ContentView: View {
// 2. @ObservedObjectでデータモデルを監視
@ObservedObject var userData: UserData
var body: some View {
TextField("Enter your name", text: $userData.name)
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(userData: UserData())
}
}
実用方法の例 (手順は4つだけ)
ボタンタップアクションを別のクラスで受け取る方法
SwiftUIで、ボタンタップアクションを別のクラスで受け取る方法は、ViewModelを使用して実現できます。ViewModelは、アプリケーションのロジックとデータをViewから分離するための役割を果たします。ここでは、Combineフレームワークを使ったViewModelの実装方法を説明します。
1. ViewModelの定義:
まず、ViewModelを定義するために、ObservableObjectプロトコルに準拠したクラスを作成します。この例では、MyViewModelという名前のクラスを作成します。
import SwiftUI
import Combine
class MyViewModel: ObservableObject {
// ...
}
2. ボタンタップアクションの実装:
次に、ViewModel内にボタンタップアクションを処理するためのメソッドを実装します。この例では、onButtonTap()という名前のメソッドを作成します。
class MyViewModel: ObservableObject {
func onButtonTap() {
// ボタンタップ時に実行する処理をここに書く
}
}
3. SwiftUI Viewの作成:
ViewModelを使ったSwiftUI Viewを作成します。この例では、MyViewという名前のViewを作成します。ViewModelをインスタンス化し、@ObservedObjectプロパティラッパーを使って、ViewからViewModelを監視できるようにします。
struct MyView: View {
@ObservedObject var viewModel: MyViewModel
var body: some View {
// ...
}
}
4. ボタンの作成:
MyView内にボタンを作成し、タップアクションでViewModelのonButtonTap()メソッドを呼び出します。
struct MyView: View {
@ObservedObject var viewModel: MyViewModel
var body: some View {
Button(action: {
viewModel.onButtonTap()
}) {
Text("タップ")
}
}
}
これで、ボタンタップ時にMyViewModelクラスのonButtonTap()メソッドが実行されるようになりました。ViewModel内で、必要に応じてCore Dataなどの処理が行えるようになります。
ObservableとObservedの相関図
ObservableとObservedは、SwiftUIでデータの変更を監視するために使用されるプロトコルです。以下の相関図でそれぞれのプロトコルがどのように関連しているかを示しています。
┌──────────────┐
│ Observable │
└───────┬──────┘
│
│ (conforms to)
▼
┌────────────────────────┐
│ ObservableObject │
└────────┬───────────────┘
│
│ (observes)
▼
┌────────────────────────┐
│ @ObservedObject │
└────────────────────────┘
- Observable: これは、オブジェクトが監視可能であることを示すためのプロトコルです。SwiftUIでは、
ObservableObjectプロトコルが主に使用されます。 - ObservableObject:
Observableに適合するプロトコルで、オブジェクトが変更を検出するために監視できることを示します。ObservableObjectに準拠したクラスは、プロパティに@Publishedラッパーを使用して、変更を通知することができます。 - @ObservedObject: SwiftUIのプロパティラッパーで、
ObservableObjectに適合するオブジェクトを監視します。@ObservedObjectが監視するオブジェクトのプロパティが変更されると、関連するビューが自動的に更新されます。
この相関図は、Observable(主にObservableObject)とObserved(@ObservedObject)がどのように相互作用し、オブジェクトの変更を監視するためにどのように関連しているかを示しています。
まとめ
まとめると、@ObservableObjectと@ObservedObjectは、データの共有と更新を簡単に行うためのSwiftUIの機能です。@ObservableObjectはデータの状態管理と変更の監視を行い、@ObservedObjectはビューにデータの変更を通知して自動的に更新を行います。適切に使い分けることで、効率的にデータドリブンなアプリケーションを開発することができます。
関連リンク:



コメント