Как правильно заказать данные из Firebase в хронологическом порядке?

Я пытаюсь заказать мои данные из Firebase, поэтому последняя запись находится наверху (например, Instagram), но я просто не могу заставить ее работать правильно. Должен ли я использовать временную метку сервера? Есть ли поле "createdAt"?

func getPosts() {
    POST_REF.observeEventType(.Value, withBlock: { snapshot in
        guard let posts = snapshot.value as? [String : [String : String]] else {
            print("No Posts Found")
            return
        }

        Post.feed?.removeAll()
        for (postID, post) in posts {
            let newPost = Post.initWithPostID(postID, postDict: post)!
            Post.feed?.append(newPost)
        }
        Post.feed? = (Post.feed?.reverse())!
        self.tableView.reloadData()
        }, withCancelBlock: { error in
            print(error.localizedDescription)
    })
}

Ответ 1

Использование только reverse() для вашего массива недостаточно, чтобы охватить все. Вам нужно подумать о разных вещах:

  • Ограничьте время получения данных, используйте append(), а затем reverse(), чтобы сэкономить время. Вам не нужно удалять весь массив за каждый раз.

  • Прокрутка триггера или будет использовать метод ячейки

Пусть начнется. Вы можете создать дочерний элемент для ваших сообщений timestamp или дата/время, являющийся глобальным. Чтобы обеспечить как Instagram секунды, я советую вам использовать время UTC. Поэтому я буду называть это: (timeUTC)

Для сортировки всего сообщения используйте метку с1970. Поэтому я буду называть это (timestamp), а затем вы можете сохранить еще один node как (reverseedimestamp) добавление - префикс к отметке времени. Поэтому, когда вы используете queryOrdered для этого node. Вы можете обрабатывать последние 5 сообщений с помощью yourQuery.queryLimited(toFirst: 5).

1. Установите дату/время UTC для timeUTC node в 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 означает универсальное время, посмотрите http://time.is/tr/UTC

2.Get since1970 timestamp для сортировки сообщений в Swift 3:

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

Теперь вы можете сохранить их в своих сообщениях Firebase, как это.

"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"
    },

Я получу пять-пять сообщений, поэтому я делаю queryLimited (toFirst: 5) в 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)
            })
        }
    })

Если пользователь достиг последнего сообщения, вы можете обработать его с помощью метода willDisplay, как показано ниже, затем вы можете вызвать функцию loadMore.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

   if self.posts.count - 1 == indexPath.row {
      // call loadMore function.
   }
}

В функции loadMore() вы можете обрабатывать последнюю метку времени публикации, а затем начальный запрос, как с этим, поэтому вы можете легко продолжить следующие первые 5 сообщений при добавлении перед массивом.

Для преобразования Swift 3, как хорошо отформатированного, посмотрите здесь: Swift 3 - UTC, чтобы метки времени, считая изменения времени устройства на 12 часов /24 часа

Ответ 2

На основании ответа @tobeiosdev я определяю свою структуру данных следующим образом:

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

Как вы можете видеть, я добавил атрибут timestamp, когда я запрашиваю свои данные с дочерним добавленным событием, я передаю эти данные объекту post, а затем добавляю этот объект в массив сообщений, из которых открывается мой стол будет кормить:

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

С помощью метода сортировки мне удалось упорядочить мои данные в порядке желаний сообщений, от самого нового до самого старого. Надеюсь, этот подход может помочь любому:).