问题
I'm working on a SwiftUI project and am having trouble getting a picker to work correctly.
I've got a hierarchy of views split into multiple files with the initial view wrapping everything in a NavigationView.
Looks something like this:
MainFile (TabView -> NavigationView)
- ListPage (NavigationLink)
-- DetailHostPage (Group.EditButton)
if editing
--- DetailViewPage
else
--- DetailEditPage (picker in a form)
The picker that I have in the DetailEditPage
does not let me change it's value, though it does display the correct current value.
Picker(selection: self.$_myObj.SelectedEnum, label: Text("Type")) {
ForEach(MyEnum.allCases, id: \.self) {
Text("\(String(describing: $0))")
}
}
If I wrap the picker in a navigation view directly then it works, but now I have a nested navigation view resulting in two back buttons, which is not what I want.
What is causing the picker not to allow it's selection to change, and how can I get it working?
EDIT
Here's an example of how to replicate this:
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:
We don't have an idea about your enum and model (_myObj) implementation.
In the next snippet is working code (copy - paste - test it) where you can see how to implement picker with enum. You can even uncomment the lines where Form is declared, if you like to have your Picker in Form
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()
}
}
UPDATE change your code
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())
}
}
}
and see what happens
I think, you just misunderstood what the editing mode is for.
来源:https://stackoverflow.com/questions/60590266/how-to-get-swiftui-picker-in-subview-working-greyed-out