问题描述
我正在处理一个 SwiftUI 项目,但无法让选择器正常工作.
I'm working on a SwiftUI project and am having trouble getting a picker to work correctly.
我将视图层次结构拆分为多个文件,其中初始视图将所有内容包装在 NavigationView 中.
I've got a hierarchy of views split into multiple files with the initial view wrapping everything in a NavigationView.
看起来像这样:
MainFile (TabView -> NavigationView)
- ListPage (NavigationLink)
-- DetailHostPage (Group.EditButton)
if editing
--- DetailViewPage
else
--- DetailEditPage (picker in a form)
我在 DetailEditPage
中的选择器不允许我更改它的值,尽管它确实显示了正确的当前值.
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?
编辑
以下是如何复制此内容的示例:
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()
}
}
推荐答案
我们不知道您的枚举和模型 (_myObj) 实现.
We don't have an idea about your enum and model (_myObj) implementation.
在下一个片段中是工作代码(复制-粘贴-测试),您可以在其中了解如何使用枚举实现选择器.如果您希望在 Form 中使用 Picker,您甚至可以取消对 Form 声明行的注释
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()
}
}
更新更改您的代码
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())
}
}
}
看看会发生什么
我想,你只是误解了编辑模式的用途.
I think, you just misunderstood what the editing mode is for.
这篇关于如何让 SwiftUI Picker 在子视图中工作?(变灰)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!