0

I'm working on application that prints name of place that has been visited according to its ID. I'm storing data in several nodes node called "placesExploredByUsers/userID" stores data about IDs of places that user have visited before and node "databaseOfPlaces" stores all IDs of places with additional info (name, location, coordinates etc.), so it works like foreign key in SQL. All of my data is stored in Firebase.

But, I'm having problem with ordering my cells in tableView in Swift. I've tried several options and this is my last modification. The problem is, that my cells are randomly reordering everytime I come to the viewController with tableView.

This is function, that should handle it.

Can anyone please help me? Thanks in advance

   func getDataToTable(){
    // setting the firebase reference
    ref = Database.database().reference()
    let userID = (Auth.auth().currentUser?.uid)!
    
    // getting information about places that user has visited
    Database.database().reference().child("placesExploredByUsers").child(userID).queryOrderedByValue().observeSingleEvent(of: .value) { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject]{
            
            // creating array of all ID of places that user has visited
            let idsOfAllPlaces = Array(dictionary.keys)
            
            for id in idsOfAllPlaces  {
                
                // getting information about places from database of ID of all places that are in app
                Database.database().reference().child("databaseOfPlaces").child(id).queryOrderedByValue().observeSingleEvent(of: .value) { (snapshot1) in
                    if let dictionary = snapshot1.value as? [String: AnyObject]{
                        // getting information about name
                        self.random = dictionary["name"]! as! String
                        // updating the table view
                        self.postData.append(self.random)
                        self.sortedList(array: self.postData)
                    }
                }
                
            }
            
        }
 
    }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Majo
  • 25
  • 6

2 Answers2

1

as per documentation

By default, a query retrieves all documents that satisfy the query in ascending order by document ID. You can specify the sort order for your data using orderBy(), and you can limit the number of documents retrieved using limit(). Note: An orderBy() clause also filters for existence of the given field. The result set will not include documents that do not contain the given field.

So use order(by: "databaseOfPlaces")

func getDataToTable(){
    // setting the firebase reference
    ref = Database.database().reference()
    let userID = (Auth.auth().currentUser?.uid)!
    
    // getting information about places that user has visited
    Database.database().reference().child("placesExploredByUsers").child(userID).order(by: "databaseOfPlaces").observeSingleEvent(of: .value) { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject]{
            
            // creating array of all ID of places that user has visited
            let idsOfAllPlaces = Array(dictionary.keys)
            
            for id in idsOfAllPlaces  {
                
                // getting information about places from database of ID of all places that are in app
                Database.database().reference().child("databaseOfPlaces").child(id).queryOrderedByValue().observeSingleEvent(of: .value) { (snapshot1) in
                    if let dictionary = snapshot1.value as? [String: AnyObject]{
                        // getting information about name
                        self.random = dictionary["name"]! as! String
                        // updating the table view
                        self.postData.append(self.random)
                        self.sortedList(array: self.postData)
                    }
                }
                
            }
            
        }
 
    }
}
Same7Farouk
  • 837
  • 9
  • 19
  • Thank you for your soon answer. However, I tried to implement this but I didn't succeeded as I did not find anything about .order(by: ) in firebase documentation. I've tried to use .queryOrdered(byChild: "databaseOfPlaces") but the result is the same. – Majo Jun 22 '20 at 10:04
0

The problem is that you call snapshot1.value as? [String: AnyObject], which means the order is lost (because items in a dictionary have no defined order).

To process the results in the order you requested them, loop over snapshot1.children. Something like:

for snap in snap1.children.allObjects as! [DataSnapshot] {
    self.random = snap.value["name"]! as! String
    self.postData.append(self.random)
    self.sortedList(array: self.postData)
}

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you for your answer. However I was unable to implement your 2. line as I was getting error "Value of type 'Any?' has no subscripts". So I checked your older posts and found something like this: let value = snapshot1.value as! NSDictionary self.random = value["name"] as! String ?? "" (rest is the same as you recommended) But 1. data are repeated multiple times 2. order is once again randomise for some reason. – Majo Jun 22 '20 at 10:17
  • 1) Can you repeat the exact line that gives that error message? 2) As I explain in my first line, calling `snapshot1.value` is the whole reason your ordering is lost. – Frank van Puffelen Jun 22 '20 at 15:30
  • Hi, sorry I forgot to reply. I used Firestore database instead of realtime database. I get info using method .order() and then I sorted array using : self.postData = self.postData.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending } to sort it alphabetically. Thank you very much for your help and interest :) – Majo Jun 26 '20 at 17:13