Порядок записей Firebase в хронологическом порядке в UITableView (сначала новый) - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь и уже довольно давно сортирую свои сообщения как самые новые в Firebase.Я знаю, что Firebase автоматически делает это при создании с childByAutoId (), но я думаю, что это может быть способ, которым я вызываю данные в UITableView.

Вот код для загрузки данных в мой массив:

Массив:

var posts = [[String : AnyObject]]()

Функция 'loadData ()':

let uid = Auth.auth().currentUser?.uid
    Database.database().reference().child("userinfo").child(uid!).observeSingleEvent(of: .value, with: { (snapshot) in
        let value = snapshot.value as? NSDictionary
        let userFilter = value?["discover_filter"] as! String

        if userFilter == "__" {
            Database.database().reference().child("posts").queryLimited(toLast: 50).observeSingleEvent(of: .value, with: { (snapshot) in

                self.posts.removeAll()

                if let postsDictionary = snapshot.value as? [String: AnyObject] {
                    for post in postsDictionary {
                        self.posts.append(post.value as! [String : AnyObject])

                    }
                    DispatchQueue.main.async {
                        self.postsTableView.reloadData()
                    }
                }
            })
        }else {
            Database.database().reference().child("posts").queryOrdered(byChild: "combinedstring").queryEqual(toValue: userFilter).queryLimited(toLast: 50).observeSingleEvent(of: .value, with: { (snapshot) in

                self.posts.removeAll()

                if let postsDictionary = snapshot.value as? [String: AnyObject] {
                    for post in postsDictionary {
                        self.posts.append(post.value as! [String : AnyObject])
                    }
                    DispatchQueue.main.async {
                        self.postsTableView.reloadData()
                    }
                }
            })
        }
    })

Я пытался исправить это сам, но не могу понять, я 'Я пробовал много разных способов, но пришел к выводу, что мне просто нужна помощь - я новичок и изучаю Swift только около 6 месяцев (самостоятельно как часть моего проекта для получения степени).

Если что-то еще потребуется, пожалуйста, дайте мне знать.

Заранее спасибо!

Структура JSON Firebase:

"posts" : {
"-LAxSTwPhGO9NStRFGK3" : {
  "activity" : "lol",
  "combinedstring" : "League of Legends_PC_Beginner",
  "communication" : "Mic",
  "console" : "PC",
  "description" : "Description...",
  "game" : "League of Legends",
  "gameimage" : "League of Legends.jpg",
  "key" : "-LAxSTwPhGO9NStRFGK3",
  "lfglfm" : "Looking for Group",
  "skill" : "Beginner",
  "timestamp" : 1524670787479,
  "uid" : "TgtlcIcd29gN2GEHLOO1QvGhAQA2",
  "username" : "danielrjjones"
},
"-LAxSbp8ilXUVY7yFG_C" : {
  "activity" : "lol",
  "combinedstring" : "Fifa 17_Xbox One_Beginner",
  "communication" : "Mic",
  "console" : "Xbox One",
  "description" : "Description...",
  "game" : "Fifa 17",
  "gameimage" : "Fifa 17.jpg",
  "key" : "-LAxSbp8ilXUVY7yFG_C",
  "lfglfm" : "Looking for Members",
  "skill" : "Beginner",
  "timestamp" : 1524670823883,
  "uid" : "TgtlcIcd29gN2GEHLOO1QvGhAQA2",
  "username" : "danielrjjones"
}
}

Код, использованный для создания моих сообщений:

import UIKit
import Firebase
import FirebaseDatabase

class CreatePostViewController: UIViewController, UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate {

@IBOutlet weak var gameTextField: UITextField!
@IBOutlet weak var activityTextField: UITextField!
@IBOutlet weak var consoleTextField: UITextField!
@IBOutlet weak var skillTextField: UITextField!
@IBOutlet weak var communicationTextField: UITextField!
@IBOutlet weak var lfglfmTextField: UITextField!
@IBOutlet weak var rulesTextView: UITextView!
@IBOutlet weak var descriptionTextView: UITextView!
@IBOutlet weak var createButton: UIButton!

var gameValue = String()

var console = ["Select Console", "Nintendo DS", "Nintendo Switch", "PC", "PS Vita", "Playstation 3", "Playstation 4", "Xbox 360", "Xbox One"]
var skill = ["Select Playing Type", "Beginner", "Experienced", "Veteran", "Pro"]
var communication = ["Select Communication","Mic", "No Mic"]
var lfglfm = ["Select LFG/LFM", "Looking for Group", "Looking for Members"]

var itemSelected = ""
var gameimage = ""
var combinedString = ""

weak var pickerView: UIPickerView?
weak var textField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    //allow tap on screen to remove text field input from screen
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))

    //UIPICKER
    let pickerView = UIPickerView()
    pickerView.delegate = self
    pickerView.dataSource = self

    gameTextField.delegate = self
    consoleTextField.delegate = self
    skillTextField.delegate = self
    communicationTextField.delegate = self
    lfglfmTextField.delegate = self

    //set pickerview for other text fields
    pickerView.showsSelectionIndicator = true

    let toolBar = UIToolbar()
    toolBar.barStyle = UIBarStyle.default
    toolBar.isTranslucent = true
    toolBar.tintColor = UIColor(red:0.00, green:0.45, blue:1.00, alpha:1.0)
    toolBar.sizeToFit()

    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(CreatePostViewController.donePicker))
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(CreatePostViewController.donePicker))

    toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true

    gameTextField.inputView = pickerView
    gameTextField.inputAccessoryView = toolBar
    consoleTextField.inputView = pickerView
    consoleTextField.inputAccessoryView = toolBar
    skillTextField.inputView = pickerView
    skillTextField.inputAccessoryView = toolBar
    communicationTextField.inputView = pickerView
    communicationTextField.inputAccessoryView = toolBar
    lfglfmTextField.inputView = pickerView
    lfglfmTextField.inputAccessoryView = toolBar

    // pickerview = pickerview
    self.pickerView = pickerView

    //extra styling
    let navImg = UIImage(named: "nav-bar")
    navigationController?.navigationBar.setBackgroundImage(navImg, for: .default)

    //createButton.colourBorder()

}

override func viewDidAppear(_ animated: Bool) {
    gameTextField.text = gameValue
    gameTextField.resignFirstResponder()
}

@objc func donePicker() {
    textField?.resignFirstResponder()
    self.view.endEditing(true)
}

//pickerview code
func textFieldDidBeginEditing(_ textField: UITextField) {
    if textField == gameTextField {
        return
    }else {
        self.pickerView?.reloadAllComponents()
    }
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if consoleTextField.isFirstResponder{
        return console.count
    }else if skillTextField.isFirstResponder{
        return skill.count
    }else if communicationTextField.isFirstResponder{
        return communication.count
    }else if lfglfmTextField.isFirstResponder{
        return lfglfm.count
    }
    return 0
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    if consoleTextField.isFirstResponder{
        return console[row]
    }else if skillTextField.isFirstResponder{
        return skill[row]
    }else if communicationTextField.isFirstResponder{
        return communication[row]
    }else if lfglfmTextField.isFirstResponder{
        return lfglfm[row]
    }
    return nil
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if consoleTextField.isFirstResponder{
        let itemselected = console[row]
        consoleTextField.text = itemselected
    }else if skillTextField.isFirstResponder{
        let itemselected = skill[row]
        skillTextField.text = itemselected
    }else if communicationTextField.isFirstResponder{
        let itemselected = communication[row]
        communicationTextField.text = itemselected
    }else if lfglfmTextField.isFirstResponder{
        let itemselected = lfglfm[row]
        lfglfmTextField.text = itemselected
    }
}

@IBAction func createPostTapped(_ sender: UIButton) {

    if gameTextField.text == "" || consoleTextField.text == "" || skillTextField.text == "" || communicationTextField.text == "" || lfglfmTextField.text == "" {
        let alert = UIAlertController(title: "Oops...", message: "You must fill out all fields to create a post. Please try again!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    } else if consoleTextField.text == "Select Console" || skillTextField.text == "Select Playing Type" || communicationTextField.text == "Select Communication" || lfglfmTextField.text == "Select LFG/LFM" {
        let alert = UIAlertController(title: "Oh no!", message: "Please select a value to create a post.", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    } else {

        if let uid = Auth.auth().currentUser?.uid {
            Database.database().reference().child("usernames").child(uid).observeSingleEvent(of: .value, with: {
                (snapshot) in
                if let userDictionary = snapshot.value as? [String: AnyObject] {
                    for user in userDictionary {
                        if let username = user.value as? String {
                            if let game = self.gameTextField.text {
                                if let activity = self.activityTextField.text {
                                    if let console = self.consoleTextField.text {
                                        if let skill = self.skillTextField.text {
                                            if let communication = self.communicationTextField.text {
                                                if let lfglfm = self.lfglfmTextField.text {
                                                    if let description = self.descriptionTextView.text {

                                                        let gameimage = "\(self.gameTextField.text!).jpg"
                                                        let combinedString = "\(self.gameTextField.text!)_\(self.consoleTextField.text as! String)_\(self.skillTextField.text as! String)"

                                                        let timeStamp = ServerValue.timestamp() as! [String:Any]

                                                        let refer = Database.database().reference().child("posts").childByAutoId()
                                                        let ref = refer.key

                                                        let postObject: Dictionary<String, Any> = [
                                                            "uid" : uid,
                                                            "username" : username,
                                                            "game" : game,
                                                            "activity" : activity,
                                                            "console" : console,
                                                            "skill" : skill,
                                                            "communication" : communication,
                                                            "lfglfm" : lfglfm,
                                                            "description" : description,
                                                            "gameimage" : gameimage,
                                                            "combinedstring" : combinedString,
                                                            "timestamp" : timeStamp,
                                                            "key" : ref,
                                                            ]

                                                        refer.setValue(postObject)

                                                        //Database.database().reference().child("posts").childByAutoId().setValue(postObject)

                                                        let alert = UIAlertController(title: "Success!", message: "Your post was added successfully.", preferredStyle: .alert)
                                                        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                                                            //code will run when ok button is pressed
                                                            let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoggedInVC")
                                                            self.present(vc!, animated: true, completion: nil)
                                                        }))
                                                        self.present(alert, animated: true, completion: nil)

                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            })
        }
    }
}
}

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Это должно работать:

Database.database().reference().child("posts").queryOrderedByKey().queryLimited(toLast: 50).observeSingleEvent(of: .value, with: { (snapshot: DataSnapshot) in
    self.posts.removeAll()
    for child in snapshot.children.allObjects as [DataSnapshot] {
        self.posts.append(child.value as? [String: AnyObject])
    }

    DispatchQueue.main.async {
        self.postsTableView.reloadData()
    }
})

Изменения:

  1. Явно вызовите queryOrderedByKey(), чтобы дать понять, что мы хотим, чтобы результаты были упорядочены по ключу.
  2. Зацикливание snapshot.children в замыкании, так как преждевременное преобразование в [String: AnyObject] теряет информацию для заказа.
0 голосов
/ 25 апреля 2018

(после комментариев к ответу) Решение состоит в том, чтобы добавить для каждого вашего "поста" определенное поле типа номер (называемое, например, timestamp) и назначить значение метки времени создания, умноженное на - 1

Рекомендованным значением для отметки времени является время эпохи, см. Получить время эпохи Unix в Swift .

Затем вы сортируете запрос по значению этого поля, например:

Database.database().reference().child("posts").queryOrdered(byChild: "timestamp")...

Таким образом, самые новые сообщения будут появляться первыми

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...