Swiftui 如何在其他属性更改时添加可观察属性

Swiftui 如何在其他属性更改时添加可观察属性,swiftui,combine,Swiftui,Combine,我有下面的模型对象,我使用它为每一行填充一个列表,其中包含一个切换,该切换绑定到度量。isSelected final class Model: ObservableObject { struct Measurement: Identifiable { var id = UUID() let name: String var isSelected: Binding<Bool> var selected: Bo

我有下面的模型对象,我使用它为每一行填充一个
列表
,其中包含一个
切换
,该切换绑定到
度量。isSelected

final class Model: ObservableObject {

    struct Measurement: Identifiable {
        var id = UUID()
        let name: String
        var isSelected: Binding<Bool>

        var selected: Bool = false

        init(name: String) {
            self.name = name

            let selected = CurrentValueSubject<Bool, Never>(false)
            self.isSelected = Binding<Bool>(get: { selected.value }, set: { selected.value = $0 })
        }
    }

    @Published var measurements: [Measurement]
    @Published var hasSelection: Bool = false  // How to set this?

    init(measurements: [Measurement]) {
        self.measurements = measurements
    }
}

这里有一个我想要实现的截图。可选择项目的列表,带有一个导航链接,当选择一个或多个项目时启用,当未选择任何项目时禁用


目前代码的问题是,即使您观察到
度量值的更改,它们也不会在选择更新时得到更新,因为您将
变量isSelected:Binding
声明为绑定。这意味着SwiftUI将其存储在结构之外,而结构本身不会更新(保持不变)

您可以改为声明
@Published var selectedMeasurementId:UUID?=在您的模型上为nil
,因此您的代码如下所示:


导入快捷键
进口联合收割机
结构NextView:视图{
var body:一些观点{
文本(“下一个视图”)
}
}
结构度量视图:视图{
@观测对象var模型:模型
var body:一些观点{
让我们选择=绑定(
获取:{
self.model.selectedMeasurementId!=nil
},
集合:{中的值
self.model.selectedMeasurementId=nil
}
)
返回导航视图{
清单(型号测量){测量单位:
测量视图(测量:测量,selectedMeasurementId:self.$model.selectedMeasurementId)
}
.navigationBarTitle(“选择测量值”)
.navigationBarItems(尾随:NavigationLink(目标:NextView(),isActive:hasSelection,标签:{
文本(“下一页”)
}))
}
}
}
结构度量视图:视图{
让测量:模型。测量
@绑定变量selectedMeasurementId:UUID?
var body:一些观点{
让我们选择=绑定(
获取:{
self.selectedMeasurementId==self.measurement.id
},
集合:{中的值
如果值{
self.selectedMeasurementId=self.measurement.id
}否则{
self.selectedMeasurementId=nil
}
}
)
回钉{
文本(测量名称)
.font(.subheadline)
垫片()
切换(measurement.name,isson:isSelected)
.标签隐藏()
}
}
}
最终类模型:ObservieObject{
@已发布的变量selectedMeasurementId:UUID?=nil
结构度量:可识别{
var id=UUID()
let name:String
init(名称:String){
self.name=名称
}
}
@已发布的var度量:[度量]
初始(测量:[测量]){
自我测量=测量
}
}
我不确定您希望导航栏中的导航按钮的具体行为。现在我只是在点击时将选择设置为零。您可以根据需要对其进行修改

如果要支持多选,可以使用一组选定的ID


另外,似乎iOS模拟器在导航方面有一些问题,但我在物理设备上进行了测试,它成功了。

目前代码的问题是,即使您观察到测量值的变化,它们也不会在选择更新时得到更新,因为您将
变量isSelected:Binding
声明为绑定。这意味着SwiftUI将其存储在结构之外,而结构本身不会更新(保持不变)

您可以改为声明
@Published var selectedMeasurementId:UUID?=在您的模型上为nil
,因此您的代码如下所示:


导入快捷键
进口联合收割机
结构NextView:视图{
var body:一些观点{
文本(“下一个视图”)
}
}
结构度量视图:视图{
@观测对象var模型:模型
var body:一些观点{
让我们选择=绑定(
获取:{
self.model.selectedMeasurementId!=nil
},
集合:{中的值
self.model.selectedMeasurementId=nil
}
)
返回导航视图{
清单(型号测量){测量单位:
测量视图(测量:测量,selectedMeasurementId:self.$model.selectedMeasurementId)
}
.navigationBarTitle(“选择测量值”)
.navigationBarItems(尾随:NavigationLink(目标:NextView(),isActive:hasSelection,标签:{
文本(“下一页”)
}))
}
}
}
结构度量视图:视图{
让测量:模型。测量
@绑定变量selectedMeasurementId:UUID?
var body:一些观点{
让我们选择=绑定(
获取:{
self.selectedMeasurementId==self.measurement.id
},
集合:{中的值
如果值{
self.selectedMeasurementId=self.measurement.id
}否则{
self.selectedMeasurementId=nil
}
}
)
回钉{
文本(测量名称)
.font(.subheadline)
垫片()
切换(measurement.name,isson:isSelected)
.标签隐藏()
}
}
}
最终类模型:ObservieObject{
@已发布的变量selectedMeasurementId:UUID?=nil
结构度量:可识别{
var id=UUID()
let name:String
init(名称:String){
self.name=名称
}
}
@已发布的var度量:[度量]
初始(测量:[测量]){
自我测量=测量
struct MeasurementsView: View {

    @ObservedObject var model: Model

    var body: some View {
        NavigationView {
            List(model.measurements) { measurement in
                MeasurementView(measurement: measurement)
            }
            .navigationBarTitle("Select Measurements")
            .navigationBarItems(trailing: NavigationLink(destination: NextView(), isActive: $model.hasSelection, label: {
                Text("Next")
            }))
        }
    }
}

struct MeasurementView: View {
    let measurement: Model.Measurement
    var body: some View {
        HStack {
            Text(measurement.name)
                .font(.subheadline)
            Spacer()
            Toggle(measurement.name, isOn: measurement.isSelected)
                .labelsHidden()
        }
    }
}
struct Data {
    var bool: Bool
}
class Model: ObservableObject {
    @Published var arr: [Data] = []
    var anyTrue: Bool {
        arr.map{$0.bool}.contains(true)
    }
}
import SwiftUI

struct Data: Identifiable {
    let id = UUID()
    var name: String
    var on_off: Bool
}

class Model: ObservableObject {
    @Published var data = [Data(name: "alfa", on_off: false), Data(name: "beta", on_off: false), Data(name: "gama", on_off: false)]
    var bool: Bool {
        data.map {$0.on_off} .contains(true)
    }
}



struct ContentView: View {
    @ObservedObject var model = Model()
    var body: some View {
        VStack {
        List(0 ..< model.data.count) { idx in
            HStack {
                Text(verbatim: self.model.data[idx].name)
                Toggle(isOn: self.$model.data[idx].on_off) {
                    EmptyView()
                }
            }
        }
            Text("\(model.bool.description)").font(.largeTitle).padding()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
@Published var data ....
struct ContentView: View {
    @ObservedObject var model = Model()
    var body: some View {
        NavigationView {
        List(0 ..< model.data.count) { idx in
            HStack {
                Text(verbatim: self.model.data[idx].name)
                Toggle(isOn: self.$model.data[idx].on_off) {
                    EmptyView()
                }
            }
            }.navigationBarTitle("List")
            .navigationBarItems(trailing:

                NavigationLink(destination: Text("next"), label: {
                    Text("Next")
                }).disabled(!model.bool)

            )
        }
    }
}