0

I created a tiny app that the user can upload a post to firebase database, and then in a table view, the content of all user is shown pretty much like Instagram. I got a little problem: the user's posts are shown in an alphabetical order rather than in a order where the latest uploaded posts is shown at the beginning of the tableview.

Here is my code where I downloaded the data from firebase and view it in my tableView. Does anyone see what is wrong, or why the posts are showing in alphabetical order?

import UIKit
import FirebaseStorage
import FirebaseDatabase
import FirebaseAuth
import FirebaseCore
import Firebase

class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var postsTableView: UITableView!

var posts = NSMutableArray()

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()

    self.postsTableView.delegate = self
    self.postsTableView.dataSource = self

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func loadData() {
    Database.database().reference().child("posts").observeSingleEvent(of: .value) { (snapshot) in
        if let postsDictionary = snapshot.value as? [String: AnyObject] {
        for post in postsDictionary {
            self.posts.add(post.value)

            }
            self.postsTableView.reloadData()
        }
    }
}

// MARK: - Table view data source

 func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return self.posts.count
}


 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell
    // Configure the cell...
    let post = self.posts[indexPath.row] as! [String: AnyObject]
    cell.titleLabel.text = post["title"] as? String
    cell.contentTextView.text = post["content"] as? String

        if let imageName = post["image"] as? String {

            let imageRef = Storage.storage().reference().child("images/\(imageName)")
            imageRef.getData(maxSize: 25 * 1024 * 1024) { (data, error) -> Void in
                if error == nil {
                    //successfull
                    let downloadedImage = UIImage(data: data!)
                    cell.postsImageView.image = downloadedImage
                }else {
                    // error

                    print("there was an error downloading image: \(String(describing: error?.localizedDescription))")
            }
        }
    }

            return cell
        }


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 400.0
}

@IBAction func logOutButton(_ sender: Any) {
    do {
    try Auth.auth().signOut()

        let registerSuccess = self.storyboard?.instantiateViewController(withIdentifier: "SignInVC")
        self.present(registerSuccess!, animated: true, completion: nil)
    }catch {

        let logInAlert = UIAlertController(title: "Ops something went wrong", message: "try again", preferredStyle: .alert)
        logInAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(logInAlert, animated: true, completion: nil)

    }
    let registerSuccess = self.storyboard?.instantiateViewController(withIdentifier: "SignInVC")
    self.present(registerSuccess!, animated: true, completion: nil)
}

}

Here is a image of my struct in the database

enter image description here

It would be great if someone could explain why they are shown in a alphabetical order.

Xcoder
  • 1,433
  • 3
  • 17
  • 37
Jiyar
  • 35
  • 10
  • Most likely this has to do with your query, but please post your database structure so I can confirm. We need to know how you are storing the posts – DoesData Nov 20 '17 at 21:35
  • @DoesData i have now edited the question now, i will also get a image from how my database looks in firebase – Jiyar Nov 20 '17 at 21:39
  • I need to see the database structure. You only put the code for your uploads. – DoesData Nov 20 '17 at 21:42
  • @DoesData sorry it took sometime but now i got the picture there and i have explained in wich order i have uploaded them and how they are shown in the app – Jiyar Nov 20 '17 at 22:02

1 Answers1

0

So I'm not really sure what order you want to get the data in, but like I said in my comment the problem is with your query. You need to look at toLast and toFirst you can do that here.

If you want the posts to appear from most recently uploaded (newest to oldest) you want to use toLast. toFirst provides the opposite functionality. The queries would look like this:

func loadData() {
    Database.database().reference().child("posts").queryLimited(toLast: 7).observeSingleEvent(of: .value) { (snapshot) in
        for child in snapshot.children {
            let child = child as? DataSnapshot
            self.posts.add(child.value)
            self.postsTableView.reloadData()
        }
    }
}

or

func loadData() {
    Database.database().reference().child("posts").queryLimited(toFirst: 7).observeSingleEvent(of: .value) { (snapshot) in
        for child in snapshot.children {
            let child = child as? DataSnapshot
            self.posts.add(child.value)
            self.postsTableView.reloadData()
        }
    }
}

If you employ this in your app you're going to need pagination. You can find some good blog posts on pagination with Firebase here and here.

If you want to retrieve all of the posts (unlikely) then you can use startAt or endAt source, but you'll need to know the key to start or end at.

Firebase doesn't guarantee that information is returned in order. That's why you need to query correctly and loop over the snapshot returned in the correct order to keep your posts sorted by time.

You could also add a timestamp to every post look at this question for help. Then sort your data array by the timestamps. However, I think querying correctly makes more sense.

DoesData
  • 6,594
  • 3
  • 39
  • 62
  • hmm i will try to see what i can do here im pretty new to swift and firebase, i just want to make it so the most recently uploaded `post` is shown first in the table view @DoesData – Jiyar Nov 20 '17 at 22:20
  • Like I said using toLast gets your the most recent posts. If you want the user to be able to scroll or older posts or to load more than just the posts loaded initially you'll need pagination. For example if you use toLast: 20 then it will just load the 20 most recent posts and nothing else. – DoesData Nov 20 '17 at 22:21
  • the timestamps sounds like a great idea actually untill i learn to query thing correcty because right now iam having a litle hard time understanding hahah but i greatly appreciate your help and i will try both timestamps and also fixing query i agree on fixing query i the best choice – Jiyar Nov 20 '17 at 22:26
  • could i use like `toLast: 1000 ` ? not exactly 1000 but i just mean alot alot – Jiyar Nov 20 '17 at 22:28
  • i would like to add the first example you provided if it is okey. where do i imploment the pagination? is it only a function or how do i use it? because it is the first time i hear of that word hehe @DoesData – Jiyar Nov 20 '17 at 22:33
  • Read the links I posted. Basically, in will display you call a function to load more posts as the user scrolls. – DoesData Nov 20 '17 at 22:50
  • i did add the First example you provide i got an error on `for child in snap.children` so i changed `snap` to `snapshot` i got rid of the error and i got an error on `post` aswell so i changed it to `child` after that it got me no error and everything worked untill iam in the tableview and the posts are sorted in a way like last upload is last on the tableview but i want to reverse it – Jiyar Nov 20 '17 at 23:01
  • the `queryLimited` worked perfecty but not the `toLast` i tryed to change it to `toFirst` and i got the same results – Jiyar Nov 20 '17 at 23:04
  • hey i have almost managed to create the pagination but there is something that is going wrong and im not sure what it is can you please look at my last question and see if you can spot the problem https://stackoverflow.com/questions/48330145/pagination-not-working-propperly-swift-4-firebase – Jiyar Jan 18 '18 at 21:40