SwiftUI中两个视图无法获取相同的Supabase用户ID值
解决SwiftUI跨视图共享UserData的问题
核心问题分析
你在SignInView里用@StateObject初始化UserData,这个实例仅属于SignInView本身。其他视图直接新建UserData会得到全新对象,用@EnvironmentObject但未正确注入环境的话,也拿不到登录后的supabaseUserID——本质是没有实现全局唯一实例的跨视图传递。
正确实现步骤
1. 在App入口初始化并注入全局实例
不要在SignInView里初始化UserData,而是在主App结构体中创建唯一实例,通过.environmentObject()注入到整个视图环境:
@main struct YourApp: App { // 全局唯一的UserData实例 @StateObject private var userData = UserData() var body: some Scene { WindowGroup { // 根据登录状态切换视图 if userData.supabaseUserID == nil { SignInView() } else { TodosView() } } // 注入环境,所有子视图可共享该实例 .environmentObject(userData) } }
2. 在SignInView中获取共享实例并更新
移除SignInView内的@StateObject初始化代码,改用@EnvironmentObject获取全局实例,登录成功后直接修改该实例的supabaseUserID:
struct SignInView: View { // 从环境中获取共享的UserData @EnvironmentObject var userData: UserData var body: some View { // 登录UI布局... Button("登录") { supabase.auth.signIn(email: inputEmail, password: inputPassword) { result in switch result { case .success(let session): // 更新共享实例的用户ID userData.supabaseUserID = session.user.id case .failure(let error): print(error.localizedDescription) } } } } }
3. 在TodosView中获取共享实例
同样用@EnvironmentObject获取全局实例,直接读取已更新的supabaseUserID:
struct TodosView: View { @EnvironmentObject var userData: UserData var body: some View { Text("当前用户ID: \(userData.supabaseUserID ?? "未登录")") // Todo业务UI... } }
关键注意事项
- 所有需要访问
UserData的视图必须添加@EnvironmentObject var userData: UserData,否则会触发运行时崩溃(若需容错可声明为@EnvironmentObject var userData: UserData?)。 - 禁止在子视图中用
@StateObject或@ObservedObject重新初始化UserData,否则会创建独立实例,破坏数据共享。 - 导航栈(如
NavigationStack)中的子视图会自动继承环境,无需额外注入。
内容的提问来源于stack exchange,提问作者Berkay
相关产品推荐
相关产品推荐

