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