【问题标题】:SwiftUI Picker crashes when displayed via NavigationLinkSwiftUI Picker 在通过 NavigationLink 显示时崩溃
【发布时间】:2020-05-01 03:56:25
【问题描述】:

有人有解决以下崩溃的方法吗?

我有一个通过 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 并为第一个选择器选择备用值将隐藏第二个选择器并按预期显示第三个选择器。但是,如果您操作第 3 个选择器,它将显示空白值...然后很快就会崩溃。

崩溃显示堆栈跟踪,其中包含对 [UINavigationController _navigationBar:itemEnabledAutoScrollTransition:] 的数百次调用

我认为这是一个 Apple 错误。我已经提交了 FB7534235 但我想看看是否有人有任何解决方法或建议?

一种选择是使用 .disabled() 来禁用(而不是隐藏)选择器,但这会导致用户界面更加混乱。

旁注:这似乎是与 NavgiationView()/NagivationLink() 和 Picker() 的交互——因为如果您注释掉 NagivationLink 并直接在 NavigationView 中呈现 PickerView,一切按预期工作,没有任何崩溃。

更新:示例案例已更新,使其成为子选择器的三向选择。感谢下面的@krjw 指出,在双向情况下,“else if”而不是两个单独的 if 语句可以在没有崩溃的情况下产生所需的行为......虽然我仍然不确定为什么(除非它是,“只是一个错误”)

【问题讨论】:

  • 您命名了解决方法 - 将其放在自己的视图层次结构中,例如。工作表,带有自己的 NavigationView。
  • 我遇到了类似的问题,但 PickerView 没有。但我也有数百次调用该方法。你有更多关于为什么会发生这种情况的信息吗?或者对您的错误报告有任何反馈?
  • 我也看到了。就我而言,我制作了一个按我想要的方式工作的“选择器”替代方案。在那个“选择器”中,我使用了presentationMode.wrappedValue.dismiss()。大多数时候它按预期工作。但是我遇到了一个案例,涉及如何从 TextField 中删除字符,这可能会导致您提到的错误。我不确定为什么 TextField 和我的“选择器”会有这种奇怪的交互。如果我删除了 dismiss() 调用,一切都会按预期工作。

标签: ios swift swiftui swiftui-navigationlink swiftui-picker


【解决方案1】:

我在运行 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 语句仍然没有t 帮助最终选择器....并且观察到相同的崩溃。
  • 13.3.1 iOS 把 else if 没有帮助。我在 if 下有一个选择器和一个文本
  • 我遇到了类似的问题。原来我将每个选择器的 ID 设置为选择器更改的某个值(例如,Picker(selection: $myVariable, label: Text("Broken")){...}.id(myVariable)。将 ID 更改为常量修复了它
【解决方案2】:

我遇到了同样的问题,并且输入“else if”并没有帮助。我意识到当我在Picker 出现的视图之外的某个地方有navigationBarItems 时会出现崩溃。

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

很遗憾他们有如此疯狂的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多