1

I have an array of struct called displayStruct

struct displayStruct{
let price : String!
let Description : String!
} 

I am reading data from firebase and add it to my array of struct called myPost which is initialize below

var myPost:[displayStruct] = [] 

I made a function to add the data from the database to my array of struct like this

 func addDataToPostArray(){
    let databaseRef = Database.database().reference()
    databaseRef.child("Post").queryOrderedByKey().observe(.childAdded, with:  {
        snapshot in

        let snapshotValue = snapshot.value as? NSDictionary
        let price = snapshotValue?["price"] as! String
        let description = snapshotValue?["Description"] as! String
        // print(description)
        //  print(price)

        let postArr =  displayStruct(price: price, Description: description)
        self.myPost.append(postArr)
   //if i print self.myPost.count i get the correct length

    })
}

within this closure if I print myPost.count i get the correct length but outside this function if i print the length i get zero even thou i declare the array globally(I think)

I called this method inside viewDidLoad method

   override func viewDidLoad() {
   // setup after loading the view.

    super.viewDidLoad()
   addDataToPostArray()
    print(myPeople.count) --> returns 0 for some reason


  }

I want to use that length is my method below a fucntion of tableView

public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
 return myPost.count --> returns 0
}

Any help would be greatly appreciated!

KENdi
  • 7,576
  • 2
  • 16
  • 31
packability
  • 364
  • 1
  • 2
  • 10

2 Answers2

1

Firebase observe call to the database is asynchronous which means when you are requesting for the value it might not be available as it might be in process of fetching it.

That's why your both of the queries to count returns 0 in viewDidLoad and DataSource delegeate method.

  databaseRef.child("Post").queryOrderedByKey().observe(.childAdded, with:  { // inside closure }

Inside the closure, the code has been already executed and so you have the values.

What you need to do is you need to reload your Datasource in main thread inside the closure.

   databaseRef.child("Post").queryOrderedByKey().observe(.childAdded, with:  { 
       // After adding to array
       DispatchQueue.main.asyc {
           self.tableView.reloadData()
       } 

    }
Rahul
  • 2,056
  • 1
  • 21
  • 37
1

You making a asynchronous network request inside closure and compiler doesn't wait for the response, so just Reload Table when get post data. replace the code with below it work works fine for you. All the best.

 func addDataToPostArray(){
        let databaseRef = Database.database().reference()
        databaseRef.child("Post").queryOrderedByKey().observe(.childAdded, with:  {
            snapshot in

            let snapshotValue = snapshot.value as? NSDictionary
            let price = snapshotValue?["price"] as! String
            let description = snapshotValue?["Description"] as! String
            // print(description)
            //  print(price)

            let postArr =  displayStruct(price: price, Description: description)
            self.myPost.append(postArr)
            print(self.myPost.count)
            print(self.myPost)
            self.tableView.reloadData()
       //if i print self.myPost.count i get the correct length

        })
    }
Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40