【发布时间】:2021-06-14 08:36:20
【问题描述】:
在我的 iOS 14 SwiftUI 应用程序中,当用户未登录时,我让他在显示主登录屏幕之前先经过几个设置屏幕。在最后一个设置屏幕上,我使用 NavigationLink 来显示主登录屏幕。如何清除整个导航堆栈,以便主登录屏幕成为导航堆栈中的根/第一个屏幕?
【问题讨论】:
标签: ios swift swiftui swiftui-navigationlink swiftui-navigationview
在我的 iOS 14 SwiftUI 应用程序中,当用户未登录时,我让他在显示主登录屏幕之前先经过几个设置屏幕。在最后一个设置屏幕上,我使用 NavigationLink 来显示主登录屏幕。如何清除整个导航堆栈,以便主登录屏幕成为导航堆栈中的根/第一个屏幕?
【问题讨论】:
标签: ios swift swiftui swiftui-navigationlink swiftui-navigationview
出于好奇,我开始考虑将所有内容清除到根视图的解决方案,并记得设置视图的 .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")
})
}
}
【讨论】:
.sheet() 或.fullScreenCover() 开头,self.presentationMode.wrappedValue.dismiss()
【讨论】:
现在我知道 .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
【讨论】: