SwiftUI根据布尔值无法正确显示对应视图问题排查
SwiftUI中绑定Sheet导致登录状态变量被重置的问题修复
问题根源
你遇到的核心问题是:SwiftUI的sheet在关闭时会自动将绑定的isPresented布尔值设为false。而你把控制界面切换(welcomeScreen/mapScreen)的isUserLoggedIn变量同时绑定给了sheet的显示状态,这就导致登录后sheet弹出,关闭时isUserLoggedIn被强制改为false,进而让界面错误切回welcomeScreen。
修复方案
1. 单独使用变量控制Sheet显示(最直接的解决办法)
新增一个独立的状态变量专门管理sheet的弹出,不要复用登录状态变量:
struct HomeScreen: View { @EnvironmentObject var authenticationViewModel: AuthenticationViewModel @State private var isUserLoggedIn = false @State private var isLoggedInCancelable: AnyCancellable? = nil // 新增专门控制sheet的变量 @State private var showPostLoginSheet = false // ... var body: some View { ZStack { if isUserLoggedIn { mapScreen } else { welcomeScreen } } .sheet(isPresented: $showPostLoginSheet) { // 弹窗内容 } .onAppear { isLoggedInCancelable = authenticationViewModel.publisher.sink { loggedIn in print("is user logged in: \(loggedIn)") isUserLoggedIn = loggedIn // 登录成功时触发sheet弹出 if loggedIn { showPostLoginSheet = true } } } // 页面消失时取消订阅,避免内存泄漏 .onDisappear { isLoggedInCancelable?.cancel() } } // ... }
2. 避免重复弹出Sheet(可选优化)
如果需要仅在用户首次登录时弹出sheet,可以给AuthenticationViewModel添加标记变量:
class AuthenticationViewModel: ObservableObject { @Published private var listener: AuthStateDidChangeListenerHandle? = nil @Published var hasShownPostLoginSheet = false // 新增标记 private let subject = CurrentValueSubject<Bool, Never>(false) var publisher: AnyPublisher<Bool, Never> { subject.eraseToAnyPublisher() } func listenToAuthState() { listener = Auth.auth().addStateDidChangeListener { [self] _, user in subject.send(user != nil) } } // ... }
然后在HomeScreen中添加判断逻辑:
.onChange(of: isUserLoggedIn) { newValue in if newValue && !authenticationViewModel.hasShownPostLoginSheet { showPostLoginSheet = true authenticationViewModel.hasShownPostLoginSheet = true } }
核心总结
永远不要将控制界面核心状态的变量(如登录状态)与Sheet的显示变量复用,分开管理两者的状态,就能彻底避免Sheet关闭时修改核心状态的问题。
内容的提问来源于stack exchange,提问作者favs
相关产品推荐
相关产品推荐

