SwiftUI 中 MVVM 模式中多个切换的绑定变量数组

问题描述 投票:0回答: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
        }
    }
}

以上问题请帮忙解答。

ios swift mvvm swiftui observableobject
1个回答
2
投票

实现您愿望的一种方法是使用

@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
    }
}

希望这对你有用。

最好

© www.soinside.com 2019 - 2024. All rights reserved.