小编典典

在将“ NavigationLink”放入“ NavigationView”中的“ navigationBarItems”内部后,为什么向后导航时我的SwiftUI应用会崩溃?

swift

最小的可重现示例(Xcode 11.2 beta,在Xcode 11.1中有效):

struct Parent: View {
    var body: some View {
        NavigationView {
            Text("Hello World")
                .navigationBarItems(
                    trailing: NavigationLink(destination: Child(), label: { Text("Next") })
                )
        }
    }
}

struct Child: View {
    @Environment(\.presentationMode) var presentation
    var body: some View {
        Text("Hello, World!")
            .navigationBarItems(
                leading: Button(
                    action: {
                        self.presentation.wrappedValue.dismiss()
                    },
                    label: { Text("Back") }
                )
            )
    }
}

struct ContentView: View {
    var body: some View {
        Parent()
    }
}

问题似乎在于将我放置NavigationLinknavigationBarItems嵌套于SwiftUI视图(其根视图为)的修改器内部NavigationView。崩溃报告指出,我试图弹出来,当我浏览着那个不存在的视图控制器Child,然后返回Parent

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist.'
*** First throw call stack:

如果我将其放置NavigationLink在如下所示的视图主体中,则效果很好。

struct Parent: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: Child(), label: { Text("Next") })
        }
    }
}

这是SwiftUI错误还是预期行为?

编辑:我已经在Apple的反馈助理中用ID打开了一个问题,FB7423964以防Apple有人担心:)。

编辑:我在反馈助手中打开票证表明有10多个类似的已报告问题。他们已使用更新了分辨率Resolution: Potential fix identified - For a future OS update。手指交叉,修复很快就到了。

编辑:这已在iOS 13.3中修复!


阅读 350

收藏
2020-07-07

共1个答案

小编典典

这对我来说是很痛苦的一点!我把它留了下来,直到我的大多数应用程序完成为止,并且我有足够的空间来处理崩溃问题。

我认为我们都可以同意SwifUI有一些很棒的东西,但是调试可能很困难。

我认为这是一个错误。这是我的基本原理:

  • 如果以大约半秒的异步延迟包装presentationMode dismiss调用,则应该发现程序不再崩溃。

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.presentationMode.wrappedValue.dismiss()
    

    }

  • 这向我表明,该错误是SwiftUI如何与所有其他UIKit代码进行接口以管理各种视图的一个无法预料的行为。根据您的实际代码,您可能会发现,如果视图中的复杂性较小,则崩溃实际上不会发生。例如,如果您从一个视图中退出到一个具有列表的视图,并且该列表为空,则将在没有异步延迟的情况下崩溃。另一方面,如果在该列表视图中甚至只有一个条目,则强制循环迭代以生成父视图,您将看到崩溃不会发生。

I’m not so sure how robust my solution of wrapping the dismiss call in a delay
is. I have to test it much more. If you have ideas on this, please let me
know! I’d be very happy to learn from you!

2020-07-07