【问题标题】:SwiftUI - Removing a NavigationView?SwiftUI - 删除 NavigationView?
【发布时间】:2020-08-13 20:22:13
【问题描述】:

我的入职流程的根视图有一个 NavigationView。我的应用程序的根视图是一个登录页面,其中还包含一个 NavigationView。这意味着当有人第一次启动应用程序时,他们将完成入职流程并登陆登录屏幕 - 从而在导航视图中生成导航视图。

有没有办法重置视图堆栈或在必要时简单地删除额外的导航视图?


这就是我在下面实现@New Dev 解决方案的方式。首先是 Tower 类。 (这个名字帮助我想象它是一个 ObservableObject 的事实。)它的工作是跟踪 currentPage 并让感兴趣的视图知道它什么时候发生了变化。
import Foundation
import SwiftUI
import Combine

class Tower: ObservableObject {
    enum Views {
       case onboarding, login, dashboard
    }
    let objectWillChange = PassthroughSubject<Tower, Never>()
    @Published var currentPage: Views = .onboarding {
        didSet {
            objectWillChange.send(self)
        }
    }
}

接下来是 ConductorView。当 currentPage 发生变化时,Tower 会通知它,并加载相应的视图。

struct ConductorView: View {
@EnvironmentObject var tower: Tower
    var body: some View {
        VStack {
            if tower.currentPage == .onboarding {
                ContentViewA()
            } else if tower.currentPage == .login {
                ContentViewB()
            }
        }
    }
}

最后是内容视图。

struct ContentViewA: View {
    @EnvironmentObject var tower: Tower
    var body: some View {
        Button(action: {
            self.tower.currentPage = .login
            }) {
            Text("Go to Login")
            }
        }
    }
}

除了 New Devs 非常感谢的解决方案,我还使用了来自 BLCKBIRDS 的 this article

【问题讨论】:

  • 你可以有一个根视图(没有 NavigationView),它位于所有其他流程(入职、登录、普通应用程序)之上,并使用 if/else 之类的东西在它们之间切换
  • 你能展示你的代码吗?
  • @New Dev 的评论让我看到了一篇我认为会有所帮助的文章。我只知道如何使用工作表或导航链接进行转换。但如果我能做到第三种方式,它可能会解决问题。我会尽快更新我的问题。

标签: swiftui navigationview


【解决方案1】:

我将扩展我的评论。 NavigationView/NavigationLink 不是更改视图的唯一方法 - 也可以使用简单的条件来确定呈现哪个视图。

比如说,你有一些包含登录/入职信息状态的类:

class AppState: ObservableObject {
   enum UserFlow { 
      case onboarding, login, home
   }
   @Published var userFlow: UserFlow = .onboarding
   // ...
}

然后您的RootView 可以确定要显示哪个用户流:

struct RootView: View {

   @EnvironmentObject var appState: AppState

   var body: some View {
      if appState.userFlow == .onboarding {
         OnboardingRootView()
      } else if appState.userFlow == .login {
         LoginRootView()
      } else {
         ContentView()
      }
   }
}

【讨论】: