SwiftUI中根据条件动态更新ContentView环境对象问题
解决方案
1. 集中管理用户会话状态
创建UserSession类统一管理登录状态,替代直接操作@AppStorage,确保状态变化能可靠触发视图更新:
import SwiftUI import Firebase class UserSession: ObservableObject { @Published var currentUserID: String? init() { // 初始化时从UserDefaults读取保存的用户ID currentUserID = UserDefaults.standard.string(forKey: CurrentUserDefaults.userID) } func signOut() { // 清空用户ID并同步到UserDefaults currentUserID = nil UserDefaults.standard.set(nil, forKey: CurrentUserDefaults.userID) // 执行Firebase登出 try? Auth.auth().signOut() } }
2. 修改App入口代码
用@StateObject持有UserSession,根据其currentUserID动态配置环境对象:
@main struct TSUDateApp: App { @StateObject private var userSession = UserSession() init() { FirebaseApp.configure() } var body: some Scene { WindowGroup { Group { if let userID = userSession.currentUserID { ContentView() .environmentObject(AuthViewModel()) .environmentObject(MessageListVM(userID: userID)) } else { ContentView() .environmentObject(AuthViewModel()) } } .environmentObject(userSession) // 将UserSession传入环境,方便后续调用登出 } } }
3. 更新登出逻辑
在需要登出的地方(如ViewModel或视图),直接调用UserSession的signOut方法:
// 示例:在某个ViewModel中使用 @EnvironmentObject var userSession: UserSession func signOut() { navigateToLoginView() userSession.signOut() }
原代码失效原因
- 直接遍历删除UserDefaults所有键的操作,没有通过
@AppStorage变量更新,SwiftUI无法感知状态变化,不会触发视图重绘。 - 即使
@AppStorage能感知变化,分支创建ContentView的方式可能被SwiftUI复用原有实例,导致环境对象无法更新。@StateObject管理的会话状态能确保状态变化时,body完全重计算,生成带有正确环境对象的视图。
内容的提问来源于stack exchange,提问作者Giorgi Samkharadze
相关产品推荐
相关产品推荐

