1

配列からのトグルボタンを備えた動的な数のテキストの VStack を持つ単純なユースケースがあります。

import SwiftUI

public struct Test: View {
        
    @ObservedObject public var viewModel = TestViewModel()
    
    public init() {
        
    }
    
    public var body: some View {
        VStack {
            ForEach(viewModel.models) { model in
                ToggleView(title: <#T##Binding<String>#>, switchState: <#T##Binding<Bool>#>)
                //how to add the above
            }
            
        }.padding(50)
    }
}

struct ToggleView: View {
    
    @Binding var title: String
    @Binding var switchState: Bool
    
    var body: some View {
        VStack {
            Toggle(isOn: $switchState) {
                Text(title)
            }
        }
    }
}

public class TestModel: Identifiable {
    
    @Published var state: Bool {
        didSet {
            //do something
            //publish to the view that the state has changed
        }
    }
    @Published var title: String
    
    init(state: Bool, title: String) {
        self.state = state
        self.title = title
    }
}

public class TestViewModel: ObservableObject {
    
    @Published var models: [TestModel] = [TestModel(state: false, title: "Title 1"), TestModel(state: true, title: "Title 2")]
   
}

次の疑問が生じます。

  1. MVVM パターンでは、バインド変数をモデル クラスに含めても問題ありませんか、それともビュー モデル内に配置する必要がありますか?
  2. トグル状態が変更されたときにモデルクラスからビュー/シーンに状態変更のメッセージを送信する方法は?
  3. トグル状態ごとにビュー モデルでバインディング変数の配列を使用している場合、配列のどの特定の要素が変更されたかを知る方法は? (次のコード スニペットを参照)
class ViewModel {

    @Published var dataModel: [TestModel]


    @Published var toggleStates = [Bool]() {
        didSet {
            //do something based on which element of the toggle states array has changed
        }
    }
}

上記の質問にご協力ください。

4

1 に答える 1

0

これは、あなたが望むものを達成するための 1 つの方法です。の結合力を使用する必要があることに気付くでしょうか@ObservedObject。秘訣は、インデックスを使用して、バインドする配列要素に到達することです。配列要素modelを直接ループすると、基になるバインド プロパティが失われます。

struct Test: View {

@ObservedObject public var viewModel = TestViewModel()

var body: some View {
    VStack {
        
        ForEach(viewModel.models.indices) { index in
            ToggleView(title: self.viewModel.models[index].title, switchState:  self.$viewModel.models[index].state)
        }
        
    }.padding(50)
  }
}

class TestViewModel: ObservableObject {
    @Published var models: [TestModel] = [
        TestModel(state: false, title: "Title 1"),
        TestModel(state: true, title: "Title 2")]
}


struct ToggleView: View {

    var title: String
    @Binding var switchState: Bool

    var body: some View {
        VStack {
            Toggle(isOn: $switchState) {
                Text(title)
        }
      }
   }
}

class TestModel: Identifiable {

    var state: Bool
    var title: String

    init(state: Bool, title: String) {
        self.title = title
        self.state = state
    }
}

これでうまくいくことを願っています。

一番

于 2020-09-20T10:35:57.873 に答える