Balbas Code

クロージャでModelAからModelBへの値の渡し方

公開日: 2024-01-04 23:06:14
更新日: 2024-01-04 23:27:04

クロージャについての書き方を未だ理解できていないので、まとめています。
ModelAからModelBへ渡す書き方をまとめました。

流れ的には
1.MyViewModelのupdateModelAValue()
2.ModelAのonValueChange()
3.MyViewModelのmodelA.onValueChange = { [weak self] newValue in }
4.ModelBのupdateValue()

という順番で呼ばれている。



ContentView


struct ContentView: View {
// ViewModelを監視可能なオブジェクトとして宣言
@ObservedObject var viewModel = MyViewModel()

var body: some View {
VStack {
// ModelBの現在の値を表示
Text("modelB.value: \(viewModel.displayedValue)")

// ModelAの値を更新するボタン
Button("Update Model A") {
// ViewModelを通じてModelAの値を更新
viewModel.updateModelAValue(to: "新しい値")
}

// ModelAの値を異なる値で更新する別のボタン
Button("Update Model B") {
viewModel.updateModelAValue(to: "クロージャテスト")
}

// ModelAの値をさらに異なる値で更新するもう一つのボタン
Button("Update Model C") {
viewModel.updateModelAValue(to: "クロージャテスト2")
}
}
}
}

 


ModelA


class ModelA {
// ModelAの値を保持するプロパティ
var value: String {
didSet {
// ■2■ 値が変更されるたびにonValueChangeクロージャを呼び出す
onValueChange(value)
}
}

// 変更を通知するクロージャ
var onValueChange: (String) -> Void = { _ in }

init(value: String) {
self.value = value
}
}

 


ModelB


class ModelB {
// ModelBの値を保持するプロパティ
var value: String = ""

// ■4■ ModelBの値を更新するメソッド
func updateValue(newValue: String) {
self.value = newValue
}
}

 


MyViewModel


class MyViewModel: ObservableObject {
// ModelAのインスタンス
let modelA = ModelA(value: "初期値")

// ModelBのインスタンス(プライベート)
let modelB = ModelB()

// ModelBの値をビューに表示するためのプロパティ
@Published var displayedValue: String = ""

init() {
// ■3■ ModelAのonValueChangeクロージャを設定
modelA.onValueChange = { [weak self] newValue in
// ModelBの値を更新
self?.modelB.updateValue(newValue: newValue)
// displayedValueも新しい値で更新
self?.displayedValue = newValue
}
}

// ■1■ ModelAの値を更新するメソッド
func updateModelAValue(to newValue: String) {
modelA.value = newValue
}
}


実行結果はこちらです。


closure1closure2


modelA.onValueChange = { [weak self] newValue in ... } この部分は、
ModelAvalue プロパティが変更されるたびに自動的に呼び出されます。
これは ModelAvalue プロパティに didSet オブザーバが設定されているためです。



ModelAdidSet オブザーバ


ModelA の定義において、value プロパティには didSet オブザーバが設定されています。
これは value が新しい値に設定されるたびに自動的に実行されるコードです。
このオブザーバ内で onValueChange クロージャが呼び出され、
ModelA
value が変更されたことを外部に通知します。


 


onValueChange クロージャの設定場所


onValueChange クロージャの設定は MyViewModelinit メソッド内で行われていますが、これは必ずしも init 内でなければならないわけではありません。ただし、ModelA インスタンスが生成され、使用される前に、このクロージャを設定することが重要です。init 内で設定することで、MyViewModel インスタンスが生成される際に必ずクロージャが設定されることを保証しています。


もし他の場所でクロージャを設定したい場合は、その設定が ModelAvalue が最初に変更される前に行われていることを確認する必要があります。たとえば、ある特定のビューが表示される前や、特定のユーザー操作が行われる前などに設定することも可能です。


まとめ


onValueChange クロージャは ModelAvalue が変更されるたびに自動的に呼び出されます。このクロージャの設定は MyViewModelinit メソッド内で行われており、これにより ModelA のインスタンスが利用される際に必ずクロージャが設定されている状態を保証しています。ただし、init 以外の場所で設定することも可能ですが、その場合は適切なタイミングでの設定が必要です。