弹出到根视图时缺少目标

Posted

技术标签:

【中文标题】弹出到根视图时缺少目标【英文标题】:Missing Destination when pop to Root View 【发布时间】:2020-07-27 13:13:20 【问题描述】:

我已经提到了这个 Stack Overflow 线程 SwiftUI How to Pop to root view。

但是它不适用于我的情况,当然没有答案完全适合每个人的用例,所以总是需要稍微修改答案,但当然要保持解决方案的总体轮廓。

我看过这个帖子How to popup multiple view off navigation stack,但我不确定重置场景是最好的选择吗?必须有一个“正常”的方式?

我采用的解决方案是使用 ObservableObject 并将其设置为根视图的 EnvironmentObject。

导航堆栈增加了 4 个视图:

RootView().environmentObject(AppSettings.shared)
FirstView()
SecondView()
ThirdView()
FourthView()

FirstView 的 NavigationLink isActive 状态在 AppSettings.shared 中定义,所有其他状态都在后续视图中找到,而不是在 AppSettings 中。 例如: FirstView -> SecondView SecondView isActive 状态定义在 FirstView 的 ViewModel 中,以此类推。

我想要实现的是从FourthView 弹出到RootView。所以在 FourthView 上有一个 AppSettings 类型的 environmentObject 变量(从 RootView 作为 EnvironmentObject 传递),按下按钮时,将 RootView -> FirstView isActive 状态切换为 false。

它会切换,但没有导航。 但是,在调试控制台中,这是错误

Trying to pop to a missing destination at /Library/Caches/com.apple.xbs/Sources/Monoceros/Monoceros-42.24.100/Shared/NavigationBridge_PhoneTV.swift:205

根据我的理解,将该状态切换为 false 应该会触发返回导航,但在 Stack Overflow 线程中有一个帖子使用来自 RootView -> FirstView@State 变量,并且在 EnvironmentObject 中有一个变量 moveToDashbord。然后在RootView 上添加.onReceive 修饰符以监听moveToDashboard 发布者,然后触发@State 变量。但这同样会导致相同的调试控制台消息。

简而言之,所有解决方案都会导致缺少目标控制台消息。是不是因为导航太深了?

这是一个仅限iPad项目,navigationView 样式设置为 StackedNavigationStyle。

系统详情:

Xcode 11.6

ios/PadOS Target 13.0(所以不使用 SwiftUI 2.0,如果有的话)

代码示例:

这是将 AppSettings 设置为系统范围的 EnvironmentObject 的 SceneDelegate。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 
    let contentView = LoginView().environmentObject(AppSettings.shared)
    if let windowScene = scene as? UIWindowScene 
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: contentView)
        self.window = window
        window.makeKeyAndVisible()
    

这是到 RootView 的导航链接示例

NavigationLink(destination: RootView().navigationBarBackButtonHidden(true), isActive: self.$loginViewModel.loginSuccess) 
    EmptyView()

这是来自 RootView -> FirstView 的 navigationLink 示例:

NavigationLink(destination: FirstView().environmentObject(FirstViewModel()), isActive: self.$appSettings.firstView) 
    EmptyView()
.isDetailLink(false)

注意。为了清楚起见,我不得不更改视图的实际名称。

【问题讨论】:

测试所需的示例。 How to create a Minimal, Reproducible Example 让我创建一个 它在一个干净的项目中工作.. 我的实现肯定有问题,或者视图中的某些 UI 元素导致中断。 【参考方案1】:

我发现了问题,在其中一个视图上有一个 UIViewControllerRepresentable 包装的 UIAlertController。它被构造为一个视图修饰符,提供内容。

这基本上覆盖了最终破坏导航堆栈的原始视图。

解决方案是包装一个由 View 呈现的 UIViewController,并且在 ViewController 中驻留 UIAlertController。

这个 UIAlertController 的解决方案被使用和改编SwiftUI - UIAlertController

【讨论】:

以上是关于弹出到根视图时缺少目标的主要内容,如果未能解决你的问题,请参考以下文章

弹出到根视图控制器时导航栏消失

弹出到根视图控制器时崩溃

从 Popover 关闭或弹出到根视图控制器

当标签栏点击两次时禁用自动弹出到根视图控制器

iOS10 Facebook 登录弹出到根视图控制器

选项卡栏,当来自另一个选项卡的视图控制器时弹出到根视图控制器(默认 vc)