SwiftUI Picker在通过NavigationLink显示时崩溃

5

请问有人知道以下崩溃的解决方法吗?

我有一个表单,通过NavigationLink在父级导航控制器中显示,如下所示:

    var body: some View {
        NavigationView {
            NavigationLink(destination: PickerView()) {
                Text("Picker View")
            }
        }
    }

PickerView有三个选择器。第一个选择器决定显示其他两个中的哪一个:

struct PickerView: View {
    @State var sectionValue = "pet"
    @State var petValue = "dog"
    @State var fruitValue = "apple"
    @State var foodValue = "pasta"
    var body: some View {

        Form {

            Picker(selection: $sectionValue, label: Text("What is your favorite?")) {
                Text("Pet").tag("pet")
                Text("Fruits").tag("fruits")
                Text("Foods").tag("foods")
            }

            if (sectionValue == "pet") {
                Picker(selection: $petValue, label: Text("Favorite pet")) {
                    Text("Dog").tag("dog")
                    Text("Cat").tag("cat")
                    Text("Lizard").tag("lizard")
                }
            } else if (sectionValue == "fruits") {
                Picker(selection: $fruitValue, label: Text("Favorite fruit")) {
                    Text("Apple").tag("apple")
                    Text("Pear").tag("pear")
                    Text("Orange").tag("orange")
                }
            } else if (sectionValue == "foods") {
                Picker(selection: $foodValue, label: Text("Favorite food")) {
                    Text("Pasta").tag("pasta")
                    Text("Ice Cream").tag("ice_cream")
                    Text("Bacon").tag("bacon")
                }
            }
        }
    }
}

在iOS 13.3模拟器(和设备)中,我看到以下行为:导航到PickerView并选择第一个选择器的替代值将隐藏第2个选择器并显示第3个选择器,如预期所示。但是,如果您操作第三个选择器,则会显示空白值...然后很快崩溃。崩溃显示了数百个调用[UINavigationController _navigationBar:itemEnabledAutoScrollTransition:]的堆栈跟踪。我认为这是Apple的错误。我已经提交了FB7534235,但我想知道是否有任何解决方法或建议?一种选择是使用.disabled()来禁用(而不是隐藏)选择器,但这会导致更令人困惑的用户界面。附带说明:这似乎是与NavgiationView()/NagivationLink()和Picker()的交互作用有关--因为如果您注释掉NagivationLink并直接在NavigationView中呈现PickerView,一切都按预期工作,没有任何崩溃。更新:示例案例已更新为子选择器的3种选择方式。感谢@krjw指出,在两种选择的情况下,使用"else if"而不是两个单独的if语句可以产生所需的行为,而不会发生崩溃...尽管我仍然不确定为什么(除非是一个错误)。

你给这个解决方法起了一个名字 - 把它放在自己的视图层次结构中,例如 sheet,并使用自己的 NavigationView。 - Asperi
我遇到了类似的问题,但不是在 PickerView 上。但是我也有数百个对该方法的调用。您是否有关于为什么会发生这种情况的更多信息?或者您的错误报告有任何反馈? - Josh Hrach
我也遇到了这个问题。在我的情况下,我已经制作了一个“选择器”替代品,它按照我想要的方式工作。在那个“选择器”中,我使用presentationMode.wrappedValue.dismiss()。大多数情况下,它都能按预期工作。但是我遇到了一个涉及如何从TextField中删除字符的情况,这可能会导致您提到的错误。我不确定为什么TextField和我的“选择器”会有这种奇怪的交互作用。如果我删除dismiss()调用,一切都按预期工作。 - dfrobison
2个回答

3

我遇到了同样的问题,添加了“else if”也没有帮助。后来我意识到当我在视图中的某个地方有navigationBarItems时,会出现崩溃。

因此,我将Picker移动到sheet()中,并将navigationBarItems放在同一个视图中作为解决方法。

真可惜他们有这么疯狂的错误。


3
我在运行iPadOS 13.3的iPad Pro上使用Xcode 11.3.1进行了测试。当我在第一个选择器中选择一些内容然后再次选择时,出现了奇怪的重新加载行为,但没有崩溃。
我可以在我的iPhone上复制这个崩溃。
在第二个if语句中添加一个else子句可以解决这个问题!
所以解决方案是以下代码:
struct PickerView: View {
    @State var sectionValue = "phonetic"
    @State var phoneticValue = "alpha"
    @State var fruitValue = "apple"

    var body: some View {

        Form {

            Picker(selection: $sectionValue, label: Text("Pick a Section")) {
                Text("Phonetic Alphabet").tag("phonetic")
                Text("Fruits").tag("fruits")
            }

            if (sectionValue == "phonetic") {
                Picker(selection: $phoneticValue, label: Text("Pick a letter")) {
                    Text("Alpha").tag("alpha")
                    Text("Bravo").tag("bravo")
                    Text("Charlie").tag("charlie")
                }
            }
            else if (sectionValue == "fruits") {
                Picker(selection: $fruitValue, label: Text("Pick a fruit")) {
                    Text("Apple").tag("apple")
                    Text("Pear").tag("pear")
                    Text("Orange").tag("orange")
                }
            }
        }
    }
}

struct ContentView: View {

    var body: some View {
        NavigationView {
            NavigationLink(destination: PickerView()) {
                Text("Picker View")
            }
        }
    }
}

我希望这可以帮到你!


这很有趣,因为在两种方式的切换情况下,“else”确实会改变行为。可惜,我过于简化了测试用例,在我的真实代码中,我有一个选择3个可能子选择器之一的3向选择器... 在这种情况下,我发现else语句仍然无法帮助最终的选择器... 并且观察到相同的崩溃。 - Jake
13.3.1 iOS 如果使用 else if 仍然没有帮助。我有一个选择器和一个文本框在 if 下面。 - norekhov
我遇到了类似的问题。结果发现,我将每个选择器的ID设置为某个值,而选择器会更改此值(例如,Picker(selection: $myVariable, label: Text("Broken")){...}.id(myVariable))。将ID更改为常量即可解决该问题。 - Jojodmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接