random1234 random1234 - 3 years ago 194
iOS Question

(Swift + Firebase) Convert observeSingleEvent to observe .childAdded

I have a observeSingleEvent in my viewDidLoad function and I want to change it into a observe with .childAdded so that it will listen constantly and add the objects whenever they get added to the database.

Here's the code that reads from firebase:

let parentRef = Database.database().reference().child("Recipes")

parentRef.observeSingleEvent(of: .value, with: { snapshot in

// PROCESSES VALUES RECEIVED FROM SERVER
if ( snapshot.value is NSNull ) {

// DATA WAS NOT FOUND
print("– – – Data was not found – – –")

} else {

// DATA WAS FOUND
for user_child in (snapshot.children) {

let user_snap = user_child as! DataSnapshot
let dict = user_snap.value as! [String: String?]

// DEFINE VARIABLES FOR LABELS
let recipeName = dict["Name"] as? String
let recipeDescription = dict["Description"] as? String

food.append(Element(name: recipeName!, description: recipeDescription!))

self.tableView.reloadData()
}
}
})


Another problem that I have now (besides that it only loads once) is that whenever I go to another view in the app and then come back it reads everything again so I get duplicates of everything in my tableView, will that still happen with the observe?

Edit:

Here is what my database looks like:

Recipes
-Kv7FAqgLtDrRoyGd-99
Description: "food description"
Name: "food name"
-KvBuzMUnIQXn8gpG2WL
Description: "food description2"
Name: "food name2"
-KvH6yYeJaThK7oP8xBj
Description: "food description3"
Name: "food name3"

Answer Source
  1. Change observeSingleEvent to observe.
  2. Empty food array whenever observing new values.
  3. Reload your food array outside your for-loop so that you only reload whenever you have loaded all of your items into your array.

    let parentRef = Database.database().reference().child("Recipes")
    
    // 1. Change to observe
    parentRef.observe(.value, with: { snapshot in
    
       // PROCESSES VALUES RECEIVED FROM SERVER
       if ( snapshot.value is NSNull ) {
    
           // DATA WAS NOT FOUND
           print("– – – Data was not found – – –")
    
       } else {
    
           // 2. Empty food array
           self.food = []
    
           // DATA WAS FOUND
           for user_child in (snapshot.children) {
    
               let user_snap = user_child as! DataSnapshot
               let dict = user_snap.value as! [String: String?]
    
               // DEFINE VARIABLES FOR LABELS
               let recipeName = dict["Name"] as? String
               let recipeDescription = dict["Description"] as? String
    
               food.append(Element(name: recipeName!, description: recipeDescription!))
    
            }
            // 3. reload tableview outside loop
            self.tableView.reloadData()
        }
    })
    

By emptying your food array whenever observing new values you ensure to only show the values that are present in your database and thus never having repetitive elements.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download