Sponsor Link
環境&対象
- macOS Monterery beta 5
- Xcode 13 beta5
- iOS 15
ObservableObject
Combine で定義されている Protocol です。
Apple のドキュメントは、こちら。
クラス内の @Published を付与された プロパティの変更を外部に伝達するような設定になっている Protocol です。
SwiftUI での使われ方
class ViewModel: ObservableObject {
@Published var dataValue: Int = 1
func increment() {
dataValue += 1
}
}
class MyView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
Text("DataValue: \(viewModel.dataValue)")
Button(action: { viewModel.increment() },
label: { Text("Increment") } )
}
}
上記のように、ObservableObject を View 内で、@StateObject で保持していると、@Published で宣言されている dataValue の値が変更された時に、ビューも自動で更新されます。
従来は、データ更新に合わせてビューも更新されるようにコードを記述しなければいけなかったのですが、その判断を SwiftUI 側がしてくれています。
# 内部的には、どのビューの表示に どの変数が使用されているかを分析して、表示の更新を行うようです。
アプリの別モジュールでも変更を検知したい
SwiftUI のビューであれば、@StateObject や @ObservedObject を使用することで、自動で更新が行われますが、例えば、AppKit/UIKit で作成したビューなどは、(当たり前ですが)変更に応じた自動更新は行われません。
このような時には、ObservableObject が変更されたことを検知することが必要となります。
Apple のドキュメントを確認すると ObservableObject からは、objectWillChange という publisher が提供されるハズであることがわかります。
つまり、以下のようなコードで、変更を検知することができます。
class ViewModel: ObservableObject {
@Published var dataValue: Int = 1
func increment() {
dataValue += 1
}
}
class MyNSView: NSView {
var viewModel = ViewModel()
// (1)
var viewModelSubsc: AnyCancellable? = nil
init() {
.....
// (2)
viewModelSubsc = viewModel.objectWillChange
.sink { _ in
// (3)
// update !
}
}
}
- Publisher を sink した時に保存しておくための変数です
- viewModel は、ObservableObject に準拠しているので、objectWillChange が使えます
- .sink で、通知を受け取り、必要に応じた処理を行います。
objectWillChange.send() の裏返し
うまくデータの変更を検知されずに、自分で objectWillChange.send() をコードに記述することが必要となるケースはあります。
上記は、objectWillChange.send() された通知を受け取るコードを書いているということです。
まとめ:ObservableObject の変更を検知する方法
- objectWillChange を subscribe することで変更時に通知される
- SwiftUI の View であれば、内部的に行われる
Swift 学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Swift ポケットリファレンス
Swift を学んでも、プログラミング言語の文法を全て記憶しておくことは無理なので、ちょっとした文法の確認をするために、リファレンス本を手元に置いておくと便利です。
Swift4 までしか対応していないので、相違点を理解して参照する必要があります。
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link