如果缓存数据已过时,是否只能从Firebase下载数据?

时间:2017-03-25 00:14:16

标签: swift firebase firebase-realtime-database

我的第一个使用Firebase的大应用程序刚刚启动,我遇到了一个问题 - 我很快就没有下载带宽了。

我已经研究了几种缓存数据的选项。我希望缓存数据仅在当前时使用。如果自创建缓存后Firebase上的数据已更新,我想重新下载所有数据。

我不希望在会话中多次更新数据。所以我想在获取新数据后立即删除观察者。

我尝试了两件事,但我不完全确定它们是如何工作的。

FIRDatabase.database().persistenceEnabled = true

启用持久性非常好,因为只需一行代码就可以缓存从Firebase下载的所有内容。即使应用程序未连接到互联网,它也会提取缓存数据并正常开展业务。

但我的问题是:当Firebase上的数据更新时,缓存会更新吗?看来事实并非如此。

当我进入并更改Firebase上的值并重新启动应用时,它只会给我缓存的值,而不是更新的值。

那么我试试这个:

ref.keepSynced(true)

这似乎有效。当我重新启动应用程序时,我会获得更新的值。

但接下来我的问题是:应用程序每次启动时都会下载数据(我不想要这个)或者只是需要更新时才会下载数据?

3 个答案:

答案 0 :(得分:1)

好问题!在我们的上一个应用程序中使用persistenceEnabled = true时,我和我的团队遇到了的问题(即我们不断从云端接收过时的数据)。我们甚至制作了一个简单的命令行标志,通过Xcode中的 Run 会话禁用它(又名脏黑客!)。

更完整的解决方案是使用您提到的FIRDatabaseReference.keepSynced(_:) API。再看一下这些文档似乎会按预期工作:

  

通过在某个位置调用keepSynced(true),该位置的数据将自动下载并保持同步,即使没有为该位置附加侦听器也是如此。此外,虽然位置保持同步,但不会从持久性磁盘缓存中逐出。

但是,对于大型数据集,我建议在根节点上启用此行为 - 仅限于特定的子树!

答案 1 :(得分:1)

只要数据库中的某个位置存在活动侦听器,并且只有当该位置下的任何数据发生更改时,您的应用才会同步Firebase实时数据库中的数据。当您使用keepSynced时,您实际上是在引用的位置附加一个侦听器。

当您的应用程序进程停止时,将有效删除所有侦听器。当您的应用程序进程再次启动时,没有任何旧的侦听器再次附加。您必须执行代码才能获得新的侦听器。如果未附加新侦听器,则不会同步新数据。换句话说,keepSynced不会在应用程序调用之间的位置建立持久同步。你必须每次都要求它。

启用持久性只是允许侦听器立即响应缓存数据,而无需等待来自服务的数据。监听器将首先接收缓存的数据,然后在此之后进行后续更新,只要它仍然附加并且服务上的数据实际上正在发生变化。

答案 2 :(得分:1)

我设法让应用程序做我想做的事情,虽然它可能不是最优雅的方式。

1。)我在persistenceEnabled中致电didFinishLaunchingWithOptions。这会缓存从Firebase检索到的所有数据,以便在下次应用启动时立即使用。

2.)我不要在数据库引用上调用keepSynced。否则应用程序会在每次加载应用程序时下载所有数据(不是我想要的)。

3。)如果有新数据,则处理两次 - 一次处理缓存数据,然后处理器检测到新数据一次。在第二次处理数据后,我删除了观察者。我使用计数器来判断它是第一次还是第二次处理数据。

4。)如果没有新数据,则只处理一次,不下载任何内容。

这有效地允许我仅在设备上缓存的数据过期时才下载数据。否则使用缓存的数据。

以下是一些要演示的代码:

// First download is cached data, second one is updated live data if there is updated data on Firebase

    var timesDownloaded = 0

    func downloadPops(andOnCompletion completion:@escaping ()->()){

        let baseRef = FIRDatabase.database().reference().child("SomeChild")

        baseRef.observe(.value, with: { snapshot in

            if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {

                self.timesDownloaded+=1

                // Handle the data

            }

            // First download is cached data, second one is updated live data if there is updated data on Firebase

            if self.timesDownloaded > 1 {

                print("Showing updated data")

                baseRef.removeAllObservers()

            } else {

                print("Showing cached data")

            }

            completion()

        })

    }