Leonif Nif Leonif Nif - 15 days ago 6
Swift Question

Cant find in stack work answer on: How to know when Firebase retrieved data

please explain where (method or maybe exists observe with competition method) I need retrieve data from Firebase. What is best practices?

var ref:FIRDatabaseReference!

ref = FIRDatabase.database().reference()

//filling ShopList by favorite
ref.child("goods").observeSingleEvent(of:.value, with: {(snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {

print("my app: 1. Start ObserveSingle")

for snap in snapshots {

let g = Good()
g.barcode = String(describing: snap.childSnapshot(forPath: "barcode").value!)
g.name = snap.childSnapshot(forPath: "name").value! as! String
g.price = snap.childSnapshot(forPath: "minprice").value! as! Double
g.favorite = snap.childSnapshot(forPath: "favorite").value! as! Bool

if g.favorite {//избранные товары
DataService.dataService.dbShopList.append(g)
}
}

print("my app: 2. Observe finished \(DataService.dataService.dbShopList.count)")
}

})

print("my app: 3. observe finished \(DataService.dataService.dbShopList.count)")


How to understand when and where finished step 2

Debug below

my app: 3. observe finished 0
my app: 1. Start ObserveSingle
my app: 2. Observe finished 3

Jay Jay
Answer

Firebase data is only valid within the closure following the observe. So when you call

ref.child("goods").observeSingleEvent(of:.value, with: { 
     //this is the closure where the data is returned and valid
})

Here's the getcha....

print("my app: 3.

will be called BEFORE

print("my app: 2.

because code executes faster than the internet!

There is a delay in Firebase returning data which will cause the closure to fire after the print statement that's outside the closure.

Work with Firebase data INSIDE the closure as that's the only time it's valid. Trying to access that data before it's ready will result in nil data as the variables will not be populated until the closure is called.

It takes time to get used to setting up sequences of events based on Firebase data being returned.

Here's some pseudo code:

myDataSource = []

Query Firebase for data {
  populate the data source with Firebase data
  reload the tableView
}

don't access the data source here as it won't be ready

We can put that into practice using a snippet of code from your question

var ref:FIRDatabaseReference!
ref = FIRDatabase.database().reference()

ref.child("goods").observeSingleEvent(of:.value, with: {(snapshot) in

     print("data from the snapshot is ready to be used")

     for child in snapshot.children {
         var g = Good()
         let snap = child as! FIRDataSnapshot
         let dict = snap.value! as! [String:String]
         g.barcode = dict["barcode"]!
         DataService.dataService.dbShopList.append(g)
     }

     print("All the firebase data was read in, show it in the tableView")
     self.tableView.reloadData()

 })

 print("This will execute before the closure completes so")
 print("  don't do anything with the Firebase data here")
Comments