How do you properly order data from Firebase chronologically

后端 未结 2 704
悲&欢浪女
悲&欢浪女 2020-12-02 14:38

I\'m trying to order my data from Firebase so the most recent post is at the top (like Instagram), but I just can\'t get it to work properly. Should I be using a server time

相关标签:
2条回答
  • 2020-12-02 15:41

    Based on @tobeiosdev answer i define my data structure like this:

    "posts" : {
    "-KcOa8GXBl08V-WXeX8P" : {
      "author" : "@giovanny.piñeros",
      "hashtags" : [ "Hello", "World" ],
      "text" : "Hola Mundo!!!!!",
      "timestamp" : 5.08180914309278E8,
      "title" : "Hello World",
      "userid" : "hmIWbmQhfgh93"
    }
    

    As you can see i've added a timestamp attribute, when i query my data with a child added event, i pass that data to a post object, then i append that object to an array of posts from which my table view will feed:

     self.posts.append(post)
     self.posts.sort(by: {$0.timestamp! > $1.timestamp!})
     self.tableViewFeed.reloadData()
    

    With the sort method i've managed to order my data in the desire order of posts, from the newest to the oldest. I Hope this approach could help anyone :).

    0 讨论(0)
  • 2020-12-02 15:43

    Using only reverse() for your array is not enough way to encompass everything. There are different things you need to think about:

    • Limit while retrieving data, use append() and then reverse() to save time. You don't need to delete all array for each time.

    • Scroll trigger or willDisplay cell method loading

    Let's start. You can create a child for your posts timestamp or date/time being global. To provide like Instagram seconds, weeks I advice you using UTC time. So I will call this: (timeUTC)

    For sorting your all post, use since1970 timestamp. So I will call this (timestamp) and then also you can keep another node as (reversedTimestamp) adding - prefix to timestamp. So when you use queryOrdered to this node. You can handle latest 5 post using with yourQuery.queryLimited(toFirst: 5).

    1.Get UTC date/time for timeUTC node in Swift 3:

            let date = Date()
            let formatter = DateFormatter()
            formatter.locale = Locale(identifier: "en_US_POSIX")
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
            formatter.timeZone = TimeZone(abbreviation: "UTC")
            let utcTimeZoneStr = formatter.string(from: date)
    

    +0000 means it's universal time, look at http://time.is/tr/UTC

    2.Get since1970 timestamp to sort posts in Swift 3:

    let timestamp = (Date().timeIntervalSince1970 as NSString).doubleValue
    let reversedTimestamp = -1.0 * timestamp
    

    Now, you can save them on your Firebase posts like this.

    "posts" : {
        "-KHLOy5mOSq0SeB7GBXv" : {
          "timestamp": "1475858019.2306"
          "timeUTC" : "2012-02-04 12:11:56 +0000"
        },
        "-KHLrapS0wbjqPP5ZSUY" : {
          "timestamp": "1475858010.1245"
          "timeUTC" : "2014-02-04 12:11:56 +0000"
        },
    

    I will retrieve five by five post, so I'm doing queryLimited(toFirst: 5) in viewDidLoad:

    let yourQuery = ...queryOrdered(byChild: "reverseTimestamp")
                       .queryEnding(atValue: "\(self.pageOnTimestamp)", childKey: "reverseTimestamp")
    
        yourQuery.observeSingleEvent(of: .value, with: { (snapshot) in
    
            if snapshot.value is NSNull {
    
                print("There is no post.")
    
            }
            else {
    
                yourQuery.queryLimited(toFirst: 5).observeSingleEvent(of: .value, with: { (snapshot) in
    
                    self.posts.removeAll(keepingCapacity: true)
    
                    for (i, snap) in snapshot.children.enumerated() {
    
                        if let postAllDict = snapshot.value as? [String: AnyObject] {
                            if let postDict = postAllDict[(snap as AnyObject).key as String] as? [String: AnyObject] {
    
                                let post = Post(key: (snap as AnyObject).key as String, postDict: postDict)
                                self.posts.append(post)
                            }
                        }
                    }
    
                    completion(true)
                })
            }
        })
    

    If user reached latest post, you can handle it with willDisplay method like below, then you can call loadMore function.

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    
       if self.posts.count - 1 == indexPath.row {
          // call loadMore function.
       }
    }
    

    In loadMore() function you can handle latest post's timestamp, then start-end query as with that, so you can easily continue with next first 5 posts while appending before array.

    For Swift 3 conversion as nice formatted, take a look here: Swift 3 - UTC to time ago label, thinking 12h / 24h device time changes

    0 讨论(0)
提交回复
热议问题