等待 firebase 加载,直到显示 View

Posted

技术标签:

【中文标题】等待 firebase 加载,直到显示 View【英文标题】:Wait for firebase to load until showing View 【发布时间】:2021-11-30 11:47:35 【问题描述】:

我目前正在构建一个应用程序,但遇到了一些问题。我使用 Firebase 存储用户数据,然后将其显示在一些视图中,我设法创建了完成检索数据的函数,因此解决了异步问题,但是现在当我需要显示一些数据时显示 nil,因为视图的加载速度比 firebase 加载的时间早。

我从 firebase 加载数据的功能:

func getUserFromUID(completion: @escaping (UserData)->())
    
    
    ref.child("users").child(uid).observe(.value)  (snapshot) in
        DispatchQueue.main.async 
            guard let dictionary = snapshot.value as? [String:AnyObject]  else  return
            
            var user = UserData()
            
            if let email = dictionary["email"] user.email = email  as? String 
            if let name = dictionary["name"] user.name = name  as? String 
            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)
            
            
            completion(user)
        
    
    

ChatsHomeView:

struct ChatsHomeView: View 
    
    @ObservedObject var session : SessionStore
    @State var user = UserData()
    
    func getUserInfo()
        session.getUserFromUID  (fetcheduser) in
            self.user = fetcheduser
            print("THE USER:\(user)")
        
    
    
    var body: some View 
        
        VStack
            
            Text(user.name ?? "nil")
            Button(action: 
                session.signOut()
            ) Text("Logout").padding() 
        .onAppear
            getUserInfo()
        
    

问题是,一旦用户登录,它会在 ChatsHomeView Text(user.name ?? "nil") 字段所在的位置显示 nil。我需要重新启动应用程序才能更新并显示名称。有没有办法在 firebase 完全加载之前显示应用启动屏幕,或者还有其他方法?

【问题讨论】:

【参考方案1】:

为什么不使用 firebase 离线功能,它可以帮助您自动同步当前数据,而且它不会一次又一次地加载到所有数据

您需要为您的 firebase 数据库启用 isPersistenceEnabled 属性

Database.database().isPersistenceEnabled = true

那么您需要使用keepSynced(true),以便数据保持同步。

持久性行为:

通过启用持久性,Firebase 实时数据库客户端在联机时将同步的任何数据都会持久保存到磁盘并且可以脱机使用,即使在用户或操作系统重新启动应用时也是如此。这意味着您的应用程序可以使用存储在缓存中的本地数据像在线一样工作。侦听器回调将继续触发本地更新。

keepSynced(true):

Firebase 实时数据库为活动的侦听器同步并存储数据的本地副本。此外,您可以使特定位置保持同步。

更多信息请查看documentation

【讨论】:

所以如果我理解正确的话,我需要在函数文件的顶部或函数内部定义持久化是真的吗? 您可以在初始化数据库实例后启用它 问题是,一旦用户登录并重新启动应用程序,数据就会正确加载,如果用户是新用户并登录,则在用户重新启动应用程序之前不会显示值:/ 不需要重启应用,你可以在viewDidAppear中调用获取函数,所以如果用户在新记录后返回屏幕会刷新数据 或者如果您在同一屏幕上插入数据,您可以在提交操作按钮成功时调用获取功能【参考方案2】:

ios 应用肯定会在任何网络操作完成之前准备好显示视图。

让第一个 VC 的 UI 与启动视图匹配可以满足保持启动屏幕可见的要求。我已经在一个 Objective-C 应用程序中完成了这项工作。在其中,第一个 VC 在 viewDidLoad 中加载启动视图的 nib 并将其设置为视图。

然后,用户快照的完成代码应检查启动 UI 是否仍然可见。如果是,它可以将 UI 更改为需要用户数据的 UI。

编辑来自 Objective-C 项目的插图:

在主情节提要中指定的第一个 VC 中,从应用的启动情节提要中获取 UI,并用它暂时覆盖您的视图。用户的看法将是发布仍在进行中。开始异步工作。完成后,将 UI 改回来...

- (void)viewDidLoad 
    [super viewDidLoad];
    
    NSString *storyboardName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
    UINavigationController *vc = [storyboard instantiateViewControllerWithIdentifier:@"LaunchVC"];
    UIView *launchView = vc.view;
    
    [self.view addSubview:launchView];
    [self startObserving:^(FIRDocumentSnapshot *snapshot, NSError *error) 
        if (!error) 
          // the async work has completed
          // setup this VC's underlying view with data from the snapshot, then uncover it
          [launchView removeFromSuperview]; 
        
    ];

【讨论】:

我应该以编程方式延迟 VC 更改吗?或者有没有办法让应用查看何时获取所有信息? @Pakenas 一旦获取信息,就会执行观察上的代码块。那时您就会知道您可以更改 UI。 我可以编辑添加我的objective-c代码,你能阅读旧的东西吗? :-) 任何事情都会有帮助!谢谢! @danh @Pakenas - 请参阅编辑。这是来自一个真正的目标 c 项目,它实现了在初始异步工作完成时让启动视图保持可见的效果。这适用于任何异步函数——即使是从设备上的缓存中进行异步加载的函数。

以上是关于等待 firebase 加载,直到显示 View的主要内容,如果未能解决你的问题,请参考以下文章

Sikuli如何用于等待按钮,直到它显示它然后单击它?

在从函数返回之前等待 Firebase 加载

Firebase 在 Promise 触发前等待加载数据库数据

Puppeteer 等待页面和 setTimeout 在 Firebase 云功能中不起作用

在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载

Redux firebase - 正确处理身份验证状态(前几毫秒状态为空,直到加载)