-1

I've already seen: Swift UITableView reloadData in a closure but it still does not work. That's why I'm creating a new thread for this.

I'm trying to insert Firestore data into a custom tableview. But when I print the numbers it returns (In the console):

"MyDogwalk.listTxt"

And no data is showing up on the tableview.

I guess all of this is relevant. (I also have 2 classes, with init etc)

class HistoryViewController: UIViewController {

    //Tableview
    @IBOutlet weak var tableView: UITableView!

    let db = Firestore.firestore()

    var list: [listTxt] = []


    override func viewDidLoad()
    {
        super.viewDidLoad()

        list = createArray()

        tableView.delegate = self
        tableView.dataSource = self
    }

    func createArray() -> [listTxt]
    {
        var tempTxt: [listTxt] = []

        //Authentication
        let authentication = Auth.auth().currentUser?.uid

        //Choosing collection
        db.collection("rastad").document(authentication!).collection("promenad").getDocuments()
            { (QuerySnapshot, err) in
                if err != nil
                {
                    print("Error getting documents: \(String(describing: err))");
                }
                else
                {
                    //For-loop
                    for _ in QuerySnapshot!.documents
                    {
                        self.list.removeAll()
                        let document = QuerySnapshot!.documents.first
                        let data = document!.data()
                        data.forEach { (item) in

                            let data1 = data["Dog"] as? String
                            let data2 = data["Person"] as? String
                            let data3 = data["What"] as? String
                            let data4 = data["Date"] as? String
                            let data5 = data["Time"] as? String


                            let txt = listTxt(dog: data1!, person: data2!, action: data3!, time: data4!, date: data5!)
                            print(txt)

                            tempTxt.append(txt)
                        }

                    }
                    self.tableView.reloadData()
                }
        }

        //return tempTxt
        return list
    }
}

extension HistoryViewController: UITableViewDelegate, UITableViewDataSource
{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return list.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let listPath = list[indexPath.row]

        let cell = tableView.dequeueReusableCell(withIdentifier: "ListCell") as! HistoryCell

        cell.setCell(list: listPath)

        return cell
    }


}

And.. Why is this downvoted? I got an answer that was actually working for this case, and the question is detailed enough for people to understand, isn't it?

AtulParmar
  • 4,358
  • 1
  • 24
  • 45
Putte
  • 328
  • 2
  • 17

2 Answers2

1

createArray() method runs async code, and fills tempTxt. But you are returning tempTxt before async code has been run. So instead returning from createArray method and setting its value to self.list, just do it in the method itself:

self.list = tempTxt
self.tableView.reloadData()

You are iterating over documents but always using data of documents.first. Try this:

self.list.removeAll()

for document in QuerySnapshot!.documents {
  let data = document!.data()
  data.forEach { (item) in

  let data1 = data["Dog"] as? String
  let data2 = data["Person"] as? String
  let data3 = data["What"] as? String
  let data4 = data["Date"] as? String
  let data5 = data["Time"] as? String

  self.list.append(listTxt(dog: data1!, person: data2!, action: data3!, time: data4!, date: data5!))
  }
}

self.tableView.reloadData()
Orkhan Alikhanov
  • 9,122
  • 3
  • 39
  • 60
  • That worked perfectly fine!!! Thanks!! Only one problem tho, it displays the data like this: https://imgur.com/a/4guOcEB It's only retrieving 1 of the rows, and makes a lot of duplicates. How do I solve that? Do you know? :) – Putte Feb 25 '19 at 13:12
  • I think the issue is in how you fill `tempTxt`. You have an unnecessary loop for example. – Orkhan Alikhanov Feb 25 '19 at 13:19
  • Do you mind edit the text and show a better example? :) Which loop is unnecessary? :) – Putte Feb 25 '19 at 13:21
  • Iterating over `documents` is unnecessary if you use `documents.first` always. Either remove loop or access each `document`. I updated the post – Orkhan Alikhanov Feb 25 '19 at 13:28
1

Change self.tableView.reloadData() to

self.list = tempTxt
DispatchQueue.main.async {
    self.tableView.reloadData()
}

And skip returning array from that func

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • You mean "return list" at the bottom? – Putte Feb 25 '19 at 13:14
  • Yes and change the func signature – Joakim Danielson Feb 25 '19 at 13:14
  • I got the result in the tableview now, but only one problem tho, it displays the data like this: imgur.com/a/4guOcEB It's only retrieving 1 of the rows, and makes a lot of duplicates. How do I solve that? Do you know? :) – Putte Feb 25 '19 at 13:16
  • You should iterate over all documents and get the data, now you are only accessing the first document (`first()`) – Joakim Danielson Feb 25 '19 at 13:27
  • Change outer loop to `for document in QuerySnapshot!.documents` and then skip the inner loop and just do `let data = document.data()` and then `let data1 = data["Dog"]` and so on – Joakim Danielson Feb 25 '19 at 13:30
  • So I removed ".first" and also the inner loop. But getting this error now: https://imgur.com/a/cLaQMku – Putte Feb 25 '19 at 13:32
  • Ohh!!! I understand how to solve it! Now it works perfectly! Thanks a lot!! – Putte Feb 25 '19 at 13:34