SwiftUI将数据从列表中传递到视图层次结构

时间:2019-11-21 03:56:24

标签: swift swiftui

我有一个SwiftUI应用程序。它具有一个行列表,每个行都有一个常量属性,该属性表明是否需要将其打开,以及一个属性,其指示是否处于打开状态。仅当需要打开该行时,此第二个属性才可变。这些行已排序;需要开启的功能高于不需要开启的功能。还有一个“去!”按钮,当前已禁用。如果所有需要打开的行都已启用,我希望启用它,但是我不知道如何在视图层次结构中传递数据。我也不知道Combine,所以如果答案是正确的,那么示例将是不错的选择。谢谢!

import SwiftUI

struct ListView: View {
    let models = [Model.testCase, .testCase2, .testCase3]
    var body: some View {
        NavigationView {
            List(models.sorted { first, second in
                if first.needsToBeOn { return true }
                if !second.needsToBeOn { return true }
                return false
            }) { model in
                NavigationLink(destination: EmptyView()) {
                    RowView(model: model)
                }
            }
            .navigationBarTitle(Text("Models"))
            .navigationBarItems(trailing: Button(action: {}) {
                Text("Go!").font(.title)
            }.disabled(true))
        }
    }
}

struct RowView: View {
    let model: Model
    @State var isOn = false
    var body: some View {
        HStack {
            VStack {
                Text("Must Be On:")
                Text("\(model.needsToBeOn)")
            }
            Spacer()
            VStack {
                Text("Picked Up")
                Toggle(isOn: $isOn) {
                    Text("")
                }.labelsHidden().disabled(!model.needsToBeOn)
            }
        }.padding(7.5)
    }
}

struct Model: Identifiable {
    var id: UUID

    let needsToBeOn: Bool

    static let testCase = Model(id: UUID(), needsToBeOn: true)
    static let testCase2 = Model(id: UUID(), needsToBeOn: true)
    static let testCase3 = Model(id: UUID(), needsToBeOn: false)
}

2 个答案:

答案 0 :(得分:0)

我没有机会测试,但请尝试以下代码

struct ListView: View {
@State private var models = [Model.testCase, .testCase2, .testCase3]
var body: some View {
    NavigationView {
        List(models.sorted { first, second in
            if first.needsToBeOn { return true }
            if !second.needsToBeOn { return true }
            return false
        }) { model in
            NavigationLink(destination: EmptyView()) {
                RowView(model: self.$model)
            }
        }
        .navigationBarTitle(Text("Models"))
        .navigationBarItems(trailing: Button(action: {}) {
            Text("Go!").font(.title)
        }.disabled(true))
    }
   }
 }



struct RowView: View {
@Binding var model: Model
@State var isOn = false
var body: some View {
    HStack {
        VStack {
            Text("Must Be On:")
            Text("\(model.needsToBeOn)")
        }
        Spacer()
        VStack {
            Text("Picked Up")
            Toggle(isOn: $isOn) {
                Text("")
                model.needsToBeOn = self.isOn
            }.labelsHidden().disabled(!model.needsToBeOn)
        }
    }.padding(7.5)
}

}

答案 1 :(得分:0)

看起来像在工作。

struct ListView: View {
    @State var models = [Model.testCase0, .testCase1, .testCase2, .testCase3]

    var body: some View {
        NavigationView {
            List(models.enumerated().sorted { first, second in
                first.element.needsToBeOn ? true : !second.element.needsToBeOn
            }, id: \.element.id) { e in
                NavigationLink(destination: EmptyView()) {
                    RowView(model: self.$models[e.offset])
                }
            }
            .navigationBarTitle(Text("Models"))
            .navigationBarItems(
                leading:
                Button(action: {
                    self.models.append(Model(needsToBeOn: true))
                    print(self.models.map{$0.needsToBeOn})
                }) {
                    Text("Add")
                },
                trailing: Button(action: {}) {
                    Text("Go!").font(.title)
                    // optionally we filter to take only obligatory switches into account
                }.disabled(!(models.filter({ $0.needsToBeOn}).reduce(true, { (r, m) in
                    r && m.needsToBeOn == m.isActuallyOn
                }))))
        }
    }
}



struct RowView: View {
    @Binding var model: Model
    var body: some View {
        HStack {
            VStack {
                Text("Must Be On:")
                Text("\(model.needsToBeOn.description)")
            }
            Spacer()
            VStack {
                Text("Picked Up")
                Toggle(isOn: $model.isActuallyOn) {
                    Text("")
                }.labelsHidden().disabled(!model.needsToBeOn)
            }
        }.padding(7.5)
    }
}

struct Model: Identifiable {
    var id = UUID()
    var needsToBeOn: Bool
    var isActuallyOn: Bool = false

    static let testCase0 = Model(needsToBeOn: false) // to check the sorting
    static let testCase1 = Model(needsToBeOn: true)
    static let testCase2 = Model(needsToBeOn: true)
    static let testCase3 = Model(needsToBeOn: false)
}