0

I've been trying to retrieve some data from firebase and store it in arrays. But I've got a problem when I try to append the data.

I can store the data into arrays only in the closure and outside of the closure, i all the sudden lose all the values inside of the arrays. Why does this happen? Please help me to find what I'm missing...

        var names = [String]()
        var txts = [String]()
        var imgUrls = [String]()

Database.database().reference().child("Posts").child("dummy").observe(.value) { (snapshot) in
                guard let snapshots = snapshot.children.allObjects as? [DataSnapshot] else {
                    return
                }
                for snap in snapshots {
                    let autoId = snap.key as String
                    Database.database().reference().child("Posts").child("dummy").child(autoId).observe(.value, with: { (snapshot) in
                        guard let data = snapshot.value as? [String: Any] else {return}

                        //name
                        guard let name =  data["name"] as? String else {return}
                        self.names.append(name)
                        //image
                        guard let imgUrl = data["image"] as? String else {return}
                        self.imgUrls.append(imgUrl)
                        //txt
                        guard let txt = data["text"] as? String else {return}
                        self.txts.append(txt)

                        print(self.names) //this returns all data from firebase
                        print(self.imgUrls) //this returns all data from firebase
                        print(self.txts) //this returns all data from firebase
      }
                        print(self.names) //this returns empty array
                        print(self.imgUrls) //this returns empty array
                        print(self.txts) //this returns empty array
    }
2
  • 1
    You are missing the fact that the closure is asynchronous. Look for "Swift + Closure + Async". Also, don't use 3 arrays, use only one with a custom struct that will hold a imageUrl, name and text properties. Theses three infos are sync'ed, they means nothing else. If you remove one item of self.names array, you need to do the same action for the 2 others, right? What if you want to shuffle them? Use one single array. Commented Oct 18, 2018 at 12:10
  • I have one comment regarding your use if the guard statement insufferable the for loop. In your case if an error if a nil value is detected in a snap you will exit the method without iterating through the other remaining snaps. I think if let is better suited. Or simply replace return with continue so your forloop can continue with the next object. Commented Oct 18, 2018 at 13:27

1 Answer 1

1

Could it be because you are assigning the data inside a closure which could happen in a later time. So basically the last print statement occurs before the closure statements.

I will recommend you use didSet to understand the sequence. For example:

var names: [String] = [String]() { 
    didSet {
      print(names)  // this is print each time the value is set
    }
}
var txts: [String] = [String]() {
   didSet {
    print(txts)
   }
}
var imgUrls: [String] = [String]() {
   didSet {
       print(imgUrls)
   }
}

Database.database().reference().child("Posts").child("dummy").observe(.value) { (snapshot) in 
     guard let snapshots = snapshot.children.allObjects as? [DataSnapshot] else { return }

  for snap in snapshots {
                let autoId = snap.key as String
                Database.database().reference().child("Posts").child("dummy").child(autoId).observe(.value, with: { (snapshot) in
                    guard let data = snapshot.value as? [String: Any] else {return}

                    //name
                    guard let name =  data["name"] as? String else {return}
                    self.names.append(name)
                    //image
                    guard let imgUrl = data["image"] as? String else {return}
                    self.imgUrls.append(imgUrl)
                    //txt
                    guard let txt = data["text"] as? String else {return}
                    self.txts.append(txt)
}



}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.