0
votes

I am displaying documents from my Firebase Firestore database into a UITableView. I have created an array called parties that stores my custom data model Party. The data is displaying properly, however, whenever I select a cell, the app crashes and returns the error, "Invalid document reference. Document references must have an even number of segments, but hwh3cztnfcd5aC5ZRgyPNpFUsS33 has 1."

I tried deleting the didSelectRowAt method but the error will still appear.

This is the function I have created that loads the data from Firebase Firestore.

func loadAllParties() {
    // Remove all data from the array parties.
    parties.removeAll()

    if Auth.auth().currentUser != nil {
        if let user = Auth.auth().currentUser {
            // The user's ID, unique to the Firebase project.
            let uid = user.uid

            let db = Firestore.firestore()
                db.collection(uid).order(by: "timeStamp", descending: false).getDocuments() { (snapshot, error) in
                    if error != nil {
                        print("Unable to get documents: \(error)")
                    } else {
                        for document in (snapshot!.documents) {
                            let title = document.data()["title"] as? String ?? "New Party"
                            let location = document.data()["date"] as? String ?? "No Location"
                            let date = document.data()["date"] as? String ?? "No Date"
                            let startTime = document.data()["startTime"] as? String ?? "No Start Time"
                            let endTime = document.data()["endTime"] as? String ?? "No End Time"
                            let notes = document.data()["notes"] as? String ?? "No Notes"

                            self.parties.append(Party(title: title, location: location, date: date, startTime: startTime, endTime: endTime, notes: notes))
                            self.displayOnboardingIfNeccessary()
                    }
                }
            }
        }
    } else {
        print("No user is currently signed in.")
    }
}

This is the code for didSelectRowAt.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let party = yourPartiesTableView.indexPathForSelectedRow
    let cell = tableView.cellForRow(at: party!) as! YourPartiesTableViewCell

    selectedParty = cell.titleLabel.text

    performSegue(withIdentifier: "showPartyViewController", sender: self)
}

My expectations were that when you tap the cell, it would perform a segue to the next view controller and let that view controller know what data to get from Firebase on that page.

1
Which line of code generates that error? - Doug Stevenson
Also, I will suggest that having a top-level collection for each user in your app might not be the best design. - Doug Stevenson
It is the loadPartiesData function. And also, I will make sure to change it instead of top level collection. Thank you for that suggestion. - user10166622
I don't see anything in what you've shown that would cause that error to happen. Have you narrowed it down to a specific line? Use your debugger and/or log messages. - Doug Stevenson

1 Answers

0
votes

What/why is this let party = yourPartiesTableView.indexPathForSelectedRow?

You know the tapped row from indexPath.row so

let row = indexPath.row

Then get the party from your dataSource array, not your tableview.

let party = self.parties[row]

and get the title from that

let title = party.title

that being said... the other part of the question is

you tap the cell, it would perform a segue to the next view controller and let that view controller know what data to get from Firebase on that page.

Here's a couple of options to make that happen.

If you know the party's .documentID (key), you can get that and pass it to the detail view controller, where then it would load the data from Firestore based on that key.

Second option is you pass the party object itself, and it would populate from that object. The downside there is the data is not live updating.. i.e. if you pass the key, you can attach an observer to that Firestore document (node) so if any changes take place while the detail is being viewed, it will appear in the UI.

There are about 162 other options as well, but those may be a good starting point.

Note: You may want to consider adding a .document_id property to your Party class so if something changes/need to edit/delete etc, you will know which document it is via that document_id (the .documentID)