如何等待Firebase加载完成后展示视图 避免数据显示nil问题
问题解决方案
根因分析
- 视图初始化时会优先渲染默认状态,此时Firebase异步请求还未返回,
UserData的name属性为默认nil,所以显示占位文本 - 首次登录时Firebase无本地缓存,拉取数据耗时更长,视图渲染完成后才拿到返回结果;重启应用时本地已有缓存,数据加载速度快于视图渲染,因此可以正常显示
- 你当前把用户数据存在视图的
@State属性中,数据更新逻辑和全局会话状态剥离,容易出现状态不同步的问题
具体修复方案
1. 优化SessionStore全局状态管理(推荐)
把用户数据和加载状态统一放到SessionStore中管理,作为全局共享状态避免重复请求:
class SessionStore: ObservableObject { // 新增全局共享的用户数据和加载状态 @Published var currentUser: UserData? @Published var isLoadingUser = false func getUserFromUID(completion: @escaping (UserData?)->()){ isLoadingUser = true guard let uid = Auth.auth().currentUser?.uid else { isLoadingUser = false completion(nil) return } ref.child("users").child(uid).observe(.value) { [weak self] (snapshot) in DispatchQueue.main.async { defer { self?.isLoadingUser = false } guard let dictionary = snapshot.value as? [String:AnyObject] else { completion(nil) return } var user = UserData() // 建议把所有强制解包改成可选绑定,避免字段缺失崩溃 if let email = dictionary["email"] as? String { user.email = email } if let name = dictionary["name"] as? String { user.name = name } user.firstname = dictionary["firstname"] as? String ?? "" user.lastname = dictionary["lastname"] as? String ?? "" user.type = dictionary["type"] as? String ?? "" user.uid = dictionary["uid"] as? String ?? "" user.profileImageUrl = dictionary["profileImageUrl"] as? String ?? "" user.id = snapshot.key user.fcmToken2 = dictionary["fcmToken"] as? String ?? "" self?.currentUser = user completion(user) } } } }
2. 视图层加加载状态占位
在用户数据加载完成前显示加载指示器(也可以替换为自定义的启动页视图),加载完成后再展示业务内容:
struct ChatsHomeView: View { @ObservedObject var session : SessionStore var body: some View { VStack{ if session.isLoadingUser { // 这里可以替换为你的应用启动页视图 ProgressView("加载中...") } else { Text(session.currentUser?.name ?? "暂无昵称") Button(action: { session.signOut() }){ Text("Logout").padding() } } }.onAppear{ // 只有没有用户数据的时候才发起请求,避免重复调用 if session.currentUser == nil { session.getUserFromUID { _ in } } } } }
3. 额外优化建议
- 你当前用的
observe(.value)是持续监听用户节点变化,视图销毁时记得调用removeObserver移除监听,避免内存泄漏 - 如果是首次登录流程,可以在登录成功后就提前拉取用户数据,等数据拉取完成后再跳转到首页,就不会出现首页先显示nil的问题
- 所有Firebase字段读取都不要用强制解包
as!,改用可选绑定或者默认值兜底,避免后端字段缺失导致应用直接崩溃
内容的提问来源于stack exchange,提问作者Pakenas
相关产品推荐
相关产品推荐

