为什么我的 SwiftUI 应用程序在 `NavigationView` 中的 `navigationBarItems` 内放置 `NavigationLink` 后向后导航时崩溃? [英] Why does my SwiftUI app crash when navigating backwards after placing a `NavigationLink` inside of a `navigationBarItems` in a `NavigationView`?

查看:13
本文介绍了为什么我的 SwiftUI 应用程序在 `NavigationView` 中的 `navigationBarItems` 内放置 `NavigationLink` 后向后导航时崩溃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这已在 iOS 13.3 中修复!

最小的可重现示例(Xcode 11.2 beta,适用于 Xcode 11.1):

Minimal reproducible example (Xcode 11.2 beta, this works in 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()
    }
}

问题似乎在于将我的 NavigationLink 放在 navigationBarItems 修饰符中,该修饰符嵌套在根视图为 NavigationView.崩溃报告表明,当我向前导航到 Child 然后返回到 Parent 时,我正在尝试弹出一个不存在的视图控制器.

The issue seems to lie in placing my NavigationLink inside of a navigationBarItems modifier that's nested inside of a SwiftUI view whose root view is a NavigationView. The crash report indicates that I'm trying to pop to a view controller that doesn't exist when I navigate forward to Child and then back to 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 放在视图主体中,如下所示,它工作得很好.

If I were to instead place that NavigationLink in the body of the view like the below, it works just fine.

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

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

Is this a SwiftUI bug or expected behavior?

我已经在他们的反馈助手中打开了 Apple 的问题,ID 为 FB7423964,以防 Apple 的任何人关心:).

I've opened an issue with Apple in their feedback assistant with the ID FB7423964 in case anyone out there from Apple cares to weigh in :).

我在反馈助手中打开的工单表明有 10 多个类似的报告问题.他们已使用 Resolution:Potential fix known - For a future OS update 更新了该解决方案.手指交叉,修复很快就会着陆.

My open ticket in the feedback assistant indicates there are 10+ similar reported issues. They've updated the resolution with Resolution: Potential fix identified - For a future OS update. Fingers crossed that the fix lands soon.

推荐答案

这对我来说是个痛点!我离开了它,直到我的大部分应用程序完成并且我有足够的空间来处理崩溃.

This was quite a pain point for me! I left it until most of my app was completed and I had the mind space to deal with the crashing.

我想我们都同意 SwifUI 有一些非常棒的东西,但调试可能很困难.

I think we can all agree that there's some pretty awesome stuff with SwifUI but that the debugging can be difficult.

在我看来,我会说这是一个BUG.这是我的理由:

In my opinion, I would say that this is a BUG. Here is my rationale:

  • 如果你将presentationModedismiss调用包裹在大约半秒的异步延迟中,你应该会发现程序将不再崩溃.

  • If you wrap the presentationMode dismiss call in an asynchronous delay of about a half-second, you should find that the program will no longer crash.

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

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

  • This suggests to me that the bug is an unexpected behaviour way down deep in how SwiftUI interfaces with all the other UIKit code to manage the various views. Depending on your actual code, you might find that if there is some minor complexity in the view, the crash actually will not happen. For example, if you are dismissing from a view to one that has a list, and that list is empty, you will get a crash without the asynchronous delay. On the other hand, if you have even just one entry in that list view, forcing a loop iteration to generate the parent view, you'll see that the crash will not occur.

    我不太确定我在延迟中包装解雇呼叫的解决方案有多强大.我必须对其进行更多测试.如果您对此有任何想法,请告诉我!很高兴向您学习!

    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!

    这篇关于为什么我的 SwiftUI 应用程序在 `NavigationView` 中的 `navigationBarItems` 内放置 `NavigationLink` 后向后导航时崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆