0

so I have a function to retrieve the user information from a given user id:

func getUserDataFrom(_ userID: String, completion: @escaping (_ userData: DBUser) -> Void) {

    ref.child(usersTable).child(userID).observeSingleEvent(of: .value) { (snapshot) in

        if let userDic = snapshot.value as? NSDictionary {

            let userData = DBUser(with: userDic)

            completion(userData)

        }

    }

}

The problem is that this returns the local data instead of reading from Firebase. I'd like to retrieve the data from the server (as long as there's internet connection) and only read from disk if it's not available.

I know that the easiest way to accomplish this would be using a listener, but I'm making a Today Extension and they use way too much memory increasing the chances of a crash.

I've also researched about keepSynced feature but since the database reference to the users table will have a lot of children I don't know if this will affect the memory of my extension.

Long story short: I'd like to read data from Firebase once, and only read from disk if there isn't internet connection with the minimum memory usage possible.

Thank you in advance.

iDec
  • 707
  • 2
  • 8
  • 16
  • Firebase will use the internet connection if it's available and will only work with offline data if *isPersistenceEnabled* is set to true. Also, observeSingleEvent and offline are kinda unrelated; observeSingleEvent reads data once, while an observer continually watches for changes in the data.The code in your question works for me - if I go offline it reads locally and if there is an internet connection it pulls from the server. I would say the issue lies elsewhere. See [Offline Capabilities on iOS](https://firebase.google.com/docs/database/ios/offline-capabilities?authuser=0) for more info. – Jay Nov 15 '17 at 18:21
  • Yeah maybe I didn't explain myself. The snippet of code works correctly but doesn't retrieve the data from Firebase but from disk even if there's internet connection. – iDec Nov 16 '17 at 11:12

2 Answers2

0

I retrieve some explanation, I think it might help you in your case :

ObserveSingleEventType with keepSycned will not work if the Firebase connection cannot be established on time. This is especially true during appLaunch or in the appDelegate where there is a delay in the Firebase connection and the cached result is given instead. It will also not work at times if persistence is enabled and observeSingleEvent might give the cached data first. In situations like these, a continuous ObserveEventType is preferred and should be used if you absolutely need fresh data.

I think you don't have the choice to use a continuous listener. But to avoid performance issues why you don't remove yourself your listeners when you don't it anymore.

Arrabidas92
  • 1,113
  • 1
  • 9
  • 20
0

In the fresh project I created and added your code, it retrieves data from Firebase when there's a connection and when not, from local storage. Because of that, we conclude the above code is correctly fetching Firebase data from their server.

However, in my experience observeSingleEvent and offline persistence has been a tad intermittent (perhaps a 'feature'?). To fix it, force the data at the reference to stay sync'd

let usersTableRef = Database.database().reference(withPath: usersTable)
let thisUsersTableRef = usersTableRef.child(userId)
thisUsersTableRef.keepSynced(true)
//optional:  thisUsersTableRef.child("temp").setValue(true)
thisUsersTableRef.observeSingleEvent(of: .value)

See Offline Capabilities for a bit more info and further examples.

Also see this post from 2015 for some insight on observers/listeners.

Jay
  • 34,438
  • 18
  • 52
  • 81