如何在子视图中使SwiftUI Picker工作? (变灰)

时间:2020-03-08 17:39:27

标签: swift swiftui swiftui-picker

我正在处理SwiftUI项目,无法使选择器正常工作。

我已经将视图层次结构分为多个文件,初始视图将所有内容包装在NavigationView中。

看起来像这样:

MainFile (TabView -> NavigationView)
- ListPage (NavigationLink)
-- DetailHostPage (Group.EditButton)
if editing
--- DetailViewPage
else
--- DetailEditPage (picker in a form)

我在DetailEditPage中使用的选择器虽然显示了正确的当前值,但不允许我更改其值。

Picker(selection: self.$_myObj.SelectedEnum, label: Text("Type")) {
    ForEach(MyEnum.allCases, id: \.self) {
        Text("\(String(describing: $0))")
    }
}

如果我将选择器直接包装在导航视图中,那么它可以工作,但是现在我有一个嵌套的导航视图,导致有两个后退按钮,这不是我想要的。

是什么原因导致选择器不允许更改其选择,如何使它起作用?

编辑

以下是复制此示例的示例:

ContentView.swift

class MyObject: ObservableObject {
    @Published var enumValue: MyEnum

    init(enumValue: MyEnum) {
        self.enumValue = enumValue
    }
}

enum MyEnum: CaseIterable {
    case a, b, c, d
}

struct ContentView: View {
    @State private var objectList = [MyObject(enumValue: .a), MyObject(enumValue: .b)]

    var body: some View {
        NavigationView {
            List {
                ForEach(0..<objectList.count) { index in
                    NavigationLink(destination: Subview(myObject: self.$objectList[index])) {
                        Text("Object \(String(index))")
                    }
                }
            }
        }
    }
}

struct Subview: View {
    @Environment(\.editMode) var mode
    @Binding var myObject: MyObject

    var body: some View {
        HStack {
            if mode?.wrappedValue == .inactive {
                //The picker in this view shows
                SubViewShow(myObject: self.$myObject)
            } else {
                //The picker in this view does not
                SubViewEdit(myObject: self.$myObject)
            }
        }.navigationBarItems(trailing: EditButton())
    }
}

struct SubViewShow: View {
    @Binding var myObject: MyObject

    var body: some View {
        Form {
            Picker(selection: self.$myObject.enumValue, label: Text("enum values viewing")) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }
            }
        }
    }
}

struct SubViewEdit: View {
    @Binding var myObject: MyObject
    var body: some View {
        Form {
            Picker(selection: self.$myObject.enumValue, label: Text("enum values editing")) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }
            }
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

1 个答案:

答案 0 :(得分:0)

我们不了解您的枚举和模型(_myObj)的实现。

在下一个代码段中,工作代码(复制-粘贴-测试)在这里,您可以看到如何使用枚举实现选择器。如果您希望将选择器放入窗体中,甚至可以取消注释声明窗体的行的注释

import SwiftUI

struct Subview: View {
    @Binding var flag: Bool
    @Binding var sel: Int
    var body: some View {
        VStack {
            Text(String(describing: MyEnum.allCases()[sel]))
            Button(action: {
                self.flag.toggle()
            }) {
                Text("toggle")
            }
            if flag {
                FlagOnView()
            } else {
                FlagOffView(sel: $sel)
            }
        }
    }
}

enum MyEnum {
    case a, b, c, d
    static func allCases()->[MyEnum] {
        [MyEnum.a, MyEnum.b, MyEnum.c, MyEnum.d]
    }
}
struct FlagOnView: View {
    var body: some View {
        Text("flag on")
    }
}
struct FlagOffView: View {
    @Binding var sel: Int
    var body: some View {
        //Form {
            Picker(selection: $sel, label: Text("select")) {
                ForEach(0 ..< MyEnum.allCases().count) { (i) in
                    Text(String(describing:  MyEnum.allCases()[i])).tag(i)
                }
            }.pickerStyle(WheelPickerStyle())
        //}
    }
}

struct ContentView: View {
    @State var sel: Int = 0
    @State var flag = false
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: Subview(flag: $flag, sel: $sel)) {
                    Text("push to subview")
                }
                NavigationLink(destination: Text("S")) {
                    Text("S")
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

更新更改代码

struct SubViewShow: View {
    @Binding var myObject: MyObject
    @State var sel = Set<Int>()
    var body: some View {
        Form {
            List(selection: $sel) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }.onDelete { (idxs) in
                    print("delete", idxs)
                }
            }
            Picker(selection: self.$myObject.enumValue, label: Text("enum values viewing")) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }
            }.pickerStyle(SegmentedPickerStyle())
        }
    }
}

struct SubViewEdit: View {
    @Binding var myObject: MyObject
    @State var sel = Set<Int>()
    var body: some View {
        Form {
            List(selection: $sel) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }.onDelete { (idxs) in
                    print("delete", idxs)
                }
            }
            Picker(selection: self.$myObject.enumValue, label: Text("enum values editing")) {
                ForEach(MyEnum.allCases, id: \.self) {
                    Text("\(String(describing: $0))")
                }
            }
            .pickerStyle(SegmentedPickerStyle())
        }
    }
}

看看会发生什么

我认为,您只是误解了编辑模式的用途。

enter image description here