1
votes

I have two tables in my Firebase realtime database: posts and users. The structure is:

users
-- userID
---- userName
---- userProfilePicURL

posts
-- postID
---- postTimeStamp
---- postTitle
---- postContent

Now, I fetch the data in function loadData() like this:

var Ref: DatabaseReference!
Ref = Database.database().reference()

Ref.child("posts").queryOrdered(byChild: "postTimeStamp").observeSingleEvent(of: .value) { (snapshot) in

    for child in snapshot.children {

        let snap = child as! DataSnapshot
        let dict = snap.value as! [String: Any]

        // set all additional information and append to array

        self.collectionView?.reloadData()

    }

}

This works fine. However, I want to run a second query to obtain the user information (userName, userProfilePicURL) so this can be displayed as well, as all I have now is the userID. I do this as follows:

var Ref: DatabaseReference!
Ref = Database.database().reference()

Ref.child("posts").queryOrdered(byChild: "postTimeStamp").observeSingleEvent(of: .value) { (snapshot) in

    for child in snapshot.children {

        let snap = child as! DataSnapshot
        let dict = snap.value as! [String: Any]

        Ref.child("users").child(dict["userID"] as! String).observeSingleEvent(of: .value, with: { (snapUser) in

            let valueUser = snapUser.value as! [String: Any]

            // set all additional information and append to array

            self.collectionView?.reloadData()

        }

    }

}

What happens though is, it obtains the user information and displays it correctly, but the chronological order of my first query is ruined. It shows all posts by the same user, so they are ordered by userID and not by postTimeStamp. Is there a fix to this or do I need to approach this entirely different?

UPDATE: What I have found so far When I execute print(dict), everything is displayed in the correct order. So the error occurs in a later stage. When I execute dump(self.posts), which is the array with all the posts, they are displayed in the wrong order.

My guess is that instead of appending the items chronologically as requested in the first query, they are added based on the userID, so the app fetches all posts per userID. I have no idea however why this is and I can't find it on the Internet either.

1
The reason behind error is, you have used async method in for loop. So you didn't get your data in order because fetching data from firebase is asynchronized method. you have to use another array for user and manage it using useriD - DP's
Thanks for your insight. At least now I know where to look. If I understand you correctly, should I fetch the data of the post to the array and then run another function to grab the username and profile picture? Or could I maybe run this inside the cellForItemAt method, based on the userID sent within the post array? - PennyWise
You can run this inside cell for item... Another way is you can take new array for user and load user's data from that data using userId of post's array. - DP's
Thank you so much. I just tried that and it worked. Left all user information except the userID out of the post array, then with the post["userID"] I ran another query inside the cellForItemAt method, returning the values I needed and displaying them accordingly, directly to elements in the cell. Please add your solution as an answer so I can mark it as solution for future readers. Thanks again! - PennyWise

1 Answers

1
votes

Reason:

  • The reason behind error is, you have used async method in for loop.
  • So you didn't get your data in order because fetching data from firebase is asynchronized method. you have to use another array for user and manage it using useriD

Solution:

  • You can run this inside cell for item... Another way is you can take new array for user and load user's data from that data using userId of post's array.