Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios SwiftUI-在视图模型数组中更新模型时刷新模型视图_Ios_Swift_Mvvm_Swiftui_Observable - Fatal编程技术网

Ios SwiftUI-在视图模型数组中更新模型时刷新模型视图

Ios SwiftUI-在视图模型数组中更新模型时刷新模型视图,ios,swift,mvvm,swiftui,observable,Ios,Swift,Mvvm,Swiftui,Observable,问一个简单的问题,但我可能忘记了代码中的某些内容。 让我们使用图像更好地解释: 我基本上需要在选择/取消选择项目时更新“计数”和“价格” 我的代码结构如下: 型号: class ServiceSelectorModel: Identifiable, ObservableObject { var id = UUID() var serviceName: String var price: Double init(serviceName: String

问一个简单的问题,但我可能忘记了代码中的某些内容。
让我们使用图像更好地解释:

我基本上需要在选择/取消选择项目时更新“计数”和“价格


我的代码结构如下:

型号

class ServiceSelectorModel: Identifiable, ObservableObject {
    var id = UUID()

    var serviceName: String
    var price: Double
    
    init(serviceName: String, price: Double) {
        self.serviceName = serviceName
        self.price = price
    }

    @Published var selected: Bool = false
}
class ServiceSelectorViewModel: ObservableObject {
    @Published var services = [ServiceSelectorModel]()

    init() {
        self.services = [
            ServiceSelectorModel(serviceName: "SERVICE 1", price: 1.80),
            ServiceSelectorModel(serviceName: "SERVICE 2", price: 10.22),
            ServiceSelectorModel(serviceName: "SERVICE 3", price: 2.55)
        ]
    }
}
视图模型

class ServiceSelectorModel: Identifiable, ObservableObject {
    var id = UUID()

    var serviceName: String
    var price: Double
    
    init(serviceName: String, price: Double) {
        self.serviceName = serviceName
        self.price = price
    }

    @Published var selected: Bool = false
}
class ServiceSelectorViewModel: ObservableObject {
    @Published var services = [ServiceSelectorModel]()

    init() {
        self.services = [
            ServiceSelectorModel(serviceName: "SERVICE 1", price: 1.80),
            ServiceSelectorModel(serviceName: "SERVICE 2", price: 10.22),
            ServiceSelectorModel(serviceName: "SERVICE 3", price: 2.55)
        ]
    }
}
切换视图

struct ServiceToggleView: View {
    @ObservedObject var model: ServiceSelectorModel
    
    var body: some View {
        VStack(alignment: .center) {
            HStack {
                Text(model.serviceName)
                
                Toggle(isOn: $model.selected) {
                    Text(String(format: "€ +%.2f", model.price))
                        .frame(maxWidth: .infinity, alignment: .trailing)
                }
            }
            .background(model.selected ? Color.yellow : Color.clear)
        }
    }
}
struct ServiceSelectorView: View {

    @ObservedObject var serviceSelectorVM = ServiceSelectorViewModel()

    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                ForEach (serviceSelectorVM.services, id: \.id) { service in
                    ServiceToggleView(model: service)
                }
            }

            let price = serviceSelectorVM.services.filter{ $0.selected }.map{ $0.price }.reduce(0, +)

            Text("SELECTED: \(serviceSelectorVM.services.filter{ $0.selected }.count)")
            Text(String(format: "TOTAL PRICE: €%.2f", price))    
        }
    }
}
服务选择或查看

struct ServiceToggleView: View {
    @ObservedObject var model: ServiceSelectorModel
    
    var body: some View {
        VStack(alignment: .center) {
            HStack {
                Text(model.serviceName)
                
                Toggle(isOn: $model.selected) {
                    Text(String(format: "€ +%.2f", model.price))
                        .frame(maxWidth: .infinity, alignment: .trailing)
                }
            }
            .background(model.selected ? Color.yellow : Color.clear)
        }
    }
}
struct ServiceSelectorView: View {

    @ObservedObject var serviceSelectorVM = ServiceSelectorViewModel()

    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                ForEach (serviceSelectorVM.services, id: \.id) { service in
                    ServiceToggleView(model: service)
                }
            }

            let price = serviceSelectorVM.services.filter{ $0.selected }.map{ $0.price }.reduce(0, +)

            Text("SELECTED: \(serviceSelectorVM.services.filter{ $0.selected }.count)")
            Text(String(format: "TOTAL PRICE: €%.2f", price))    
        }
    }
}

在这段代码中,我能够更新模型的
选中状态
,但视图模型包含所有模型,并且应该刷新
价格
而不是更新
阵列中的模型似乎没有改变


我忘记了什么?

最简单的方法可能是将模型设置为值类型,然后更改其属性。持有它的视图模型将被更新。并更新视图以使用绑定到这些值

struct ServiceSelectorModel: Identifiable {
    var id = UUID()

    var serviceName: String
    var price: Double
    
    init(serviceName: String, price: Double) {
        self.serviceName = serviceName
        self.price = price
    }

    var selected: Bool = false
}

struct ServiceToggleView: View {
    @Binding var model: ServiceSelectorModel
...
}

...

ForEach (serviceSelectorVM.services.indices, id: \.self) { i in
    ServiceToggleView(model: $serviceSelectorVM.services[i])
}


注意:内联编写,未经测试,可能需要修复某些打字错误。如果您仔细注意,您已经创建了两个不同的单一真相来源。这就是父级未更新的原因,因为它未链接到子级

一种方法是将
ServiceSelectorModel
创建为结构,并在子视图中将
services
数组作为
@Binding
传递。下面是工作示例

视图模型-:

struct ServiceSelectorModel {
    
    var id = UUID().uuidString
    var serviceName: String
    var price: Double
    var isSelected:Bool = false
    
    init(serviceName: String, price: Double) {
        self.serviceName = serviceName
        self.price = price
    }
    
}

class ServiceSelectorViewModel: ObservableObject,Identifiable {
    
    @Published var services = [ServiceSelectorModel]()
    
    var id = UUID().uuidString
    init() {
        self.services = [
            ServiceSelectorModel(serviceName: "SERVICE 1", price: 1.80),
            ServiceSelectorModel(serviceName: "SERVICE 2", price: 10.22),
            ServiceSelectorModel(serviceName: "SERVICE 3", price: 2.55)
        ]
    }
}
struct ServiceToggleView: View {
    @Binding var model: [ServiceSelectorModel]
    
    var body: some View {
        VStack(alignment: .center) {
            ForEach(0..<model.count) { index in
                HStack{
                    Text(model[index].serviceName)
                    Toggle(isOn: $model[index].isSelected) {
                        Text(String(format: "€ +%.2f", model[index].price))
                            .frame(maxWidth: .infinity, alignment: .trailing)
                    }
                }.background(model[index].isSelected ? Color.yellow : Color.clear)
            }
            
        }
    }
}

struct ServiceSelectorView: View {
    
    @ObservedObject var serviceSelectorVM = ServiceSelectorViewModel()
    
    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                ServiceToggleView(model: $serviceSelectorVM.services)
            }
            
            let price = serviceSelectorVM.services.filter{ $0.isSelected }.map{ $0.price }.reduce(0, +)
            
            Text("SELECTED: \(serviceSelectorVM.services.filter{ $0.isSelected }.count)")
            Text(String(format: "TOTAL PRICE: €%.2f", price))
        }
    }
}
视图-:

struct ServiceSelectorModel {
    
    var id = UUID().uuidString
    var serviceName: String
    var price: Double
    var isSelected:Bool = false
    
    init(serviceName: String, price: Double) {
        self.serviceName = serviceName
        self.price = price
    }
    
}

class ServiceSelectorViewModel: ObservableObject,Identifiable {
    
    @Published var services = [ServiceSelectorModel]()
    
    var id = UUID().uuidString
    init() {
        self.services = [
            ServiceSelectorModel(serviceName: "SERVICE 1", price: 1.80),
            ServiceSelectorModel(serviceName: "SERVICE 2", price: 10.22),
            ServiceSelectorModel(serviceName: "SERVICE 3", price: 2.55)
        ]
    }
}
struct ServiceToggleView: View {
    @Binding var model: [ServiceSelectorModel]
    
    var body: some View {
        VStack(alignment: .center) {
            ForEach(0..<model.count) { index in
                HStack{
                    Text(model[index].serviceName)
                    Toggle(isOn: $model[index].isSelected) {
                        Text(String(format: "€ +%.2f", model[index].price))
                            .frame(maxWidth: .infinity, alignment: .trailing)
                    }
                }.background(model[index].isSelected ? Color.yellow : Color.clear)
            }
            
        }
    }
}

struct ServiceSelectorView: View {
    
    @ObservedObject var serviceSelectorVM = ServiceSelectorViewModel()
    
    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                ServiceToggleView(model: $serviceSelectorVM.services)
            }
            
            let price = serviceSelectorVM.services.filter{ $0.isSelected }.map{ $0.price }.reduce(0, +)
            
            Text("SELECTED: \(serviceSelectorVM.services.filter{ $0.isSelected }.count)")
            Text(String(format: "TOTAL PRICE: €%.2f", price))
        }
    }
}
struct ServiceToggleView:视图{
@绑定变量模型:[ServiceSelectorModel]
var body:一些观点{
VStack(对齐:。中心){

ForEach(0..不要担心打字错误,我只需要一个关于如何修复的建议,而不是复制/粘贴:)