【问题标题】:SwiftUI Clear Navigation StackSwiftUI 清除导航堆栈
【发布时间】:2021-06-14 08:36:20
【问题描述】:

在我的 iOS 14 SwiftUI 应用程序中,当用户未登录时,我让他在显示主登录屏幕之前先经过几个设置屏幕。在最后一个设置屏幕上,我使用 NavigationLink 来显示主登录屏幕。如何清除整个导航堆栈,以便主登录屏幕成为导航堆栈中的根/第一个屏幕?

【问题讨论】:

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


【解决方案1】:

出于好奇,我开始考虑将所有内容清除到根视图的解决方案,并记得设置视图的 .id() 会强制重新加载。

我首先将其发布为讨论点而不是实际答案,因为如果这是一种合法的方法,我对您的意见很感兴趣。

代码保持在最低限度以展示总体思路,我还没有考虑任何内存泄漏

import SwiftUI

// MARK: - SessionManager
class SessionManager: ObservableObject {
    var isLoggedIn: Bool = false {
        didSet {
            rootId = UUID()
        }
    }
    
    @Published
    var rootId: UUID = UUID()
}

// MARK: - ContentView
struct ContentView: View {
    @ObservedObject
    private var sessionManager = SessionManager()
    var body: some View {
        NavigationView {
            NavigationLink("ContentViewTwo", destination: ContentViewTwo().environmentObject(sessionManager))
        }.id(sessionManager.rootId)
    }
}

// MARK: - ContentViewTwo
struct ContentViewTwo: View {
    @EnvironmentObject
    var sessionManager: SessionManager
    
    var body: some View {
        NavigationLink("ContentViewTwo", destination: ContentViewThree().environmentObject(sessionManager))
    }
}

// MARK: - ContentViewThree
struct ContentViewThree: View {
    @EnvironmentObject
    var sessionManager: SessionManager
    
    var body: some View {
        NavigationLink("ContentViewThree", destination: ContentViewFour().environmentObject(sessionManager))
    }
}

// MARK: - ContentViewFour
struct ContentViewFour: View {
    @EnvironmentObject
    var sessionManager: SessionManager
    
    var body: some View {
        Button(action: {
            sessionManager.isLoggedIn.toggle()
        }, label: {
            Text("logout")
        })
    }
}

【讨论】:

    【解决方案2】:
    1. 您可以在根/第一个屏幕上以.sheet().fullScreenCover() 开头,
    2. 然后与 NaviagtionLink 叠加,
    3. 最后是self.presentationMode.wrappedValue.dismiss()

    【讨论】:

      【解决方案3】:

      现在我知道 .sheet().fullscreenCover(),我更喜欢这个答案,但对于 swiftUI,这是我最初的方法。

      您可以使用@State 变量来控制行为。根据您的布尔值创建两个导航视图,它们包含在 if 条件中。

      @State var showOnBoarding = true
      if $showOnBoarding {
        OnboardingNavigationView()
      } else {
        CoreNavigationView()
      }
      

      一个包含入职链接,另一个包含您的核心导航链接。一个用于您的入职,然后一个用于登录。

      您的每个导航链接也将使用 isActive Binding 参数进行初始化。

      struct OnboardingNavigationView: View {
          var body: some View {
              NavigationView {
                  NavigationLink("Step 1",destination: NextStepView(), isActive: $showOnBoarding)
                  //etc..
              }
          }
      }
      
      struct CoreNavigationView: View {
          var body: some View {
              NavigationView {
                  NavigationLink("Login Screen",destination: AccountView(), isActive: $showOnBoarding)
                  //etc..
              }
          }
      }
      

      用户登录后,您将切换该 var。您的每个 NavigationLink 都将使用绑定到 showOnBoarding 的 isActive 属性。因此,一旦登录,他们将无法返回非活动的入职屏幕,并且将在您的“新”导航堆栈中,您的登录屏幕是根屏幕。

      请参阅“使用程序化激活呈现目标视图”部分 SwiftUI NavigationLink

      【讨论】:

        猜你喜欢
        • 2015-04-13
        • 1970-01-01
        • 2015-10-31
        • 1970-01-01
        • 2020-04-26
        • 1970-01-01
        • 2019-11-25
        • 1970-01-01
        • 2021-07-11
        相关资源
        最近更新 更多