.childДобавлено с дублирующими данными queryLimited, когда .childMoved предполагалось только запускать - PullRequest
0 голосов
/ 19 октября 2019

РЕДАКТИРОВАТЬ

addChatDataListener() получает только 3 результатов из данных чата пользователей, основанных на отметке времени, и addChatChangedListener() прослушивает любые данные, которые изменились на основена отметке времени. Допустим, есть 5 чатов 1,2,3,4,5 и он получает 1,2,3 на основе метки времени, поэтому эти результаты теперь находятся на стороне клиента или в массиве. Когда я вручную обновляю отметку времени chatID 3, чтобы быть последней в БД из консоли Firebase. Только .childMoved был запущен, но когда я меняю chatID 4 (который не был захвачен). И .childMoved, и .childAdded являются дублирующими данными при запуске.

var tableView = UITableView()
var ref: DatabaseReference!
var chats = [Chat]()


override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.frame = self.view.frame
    tableView.register(ChatTableViewCell.self, forCellReuseIdentifier: "chatCell")
    self.view.addSubview(tableView)
    ref = Database.database().reference()
    addChatDataListener()
    addChatChangeListener()
}

func addChatDataListener(){
    (ref.child("user_chats").child(myUsername)).queryOrdered(byChild: "timestamp").queryLimited(toLast: 3).observe(.childAdded, with: {(snapshot) in
        let chat = self.getChatObject(snapshot: snapshot)
        print("child added: \(chat)")
        self.chats.insert(chat, at: 0)
        self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
    })
}
func addChatChangeListener(){
    (ref.child("user_chats").child(myUsername)).queryOrdered(byChild: "timestamp").observe(.childMoved, with: {(snapshot) in
        let index = self.indexOfChat(key: snapshot.key)
        let chat = self.getChatObject(snapshot: snapshot)
        print("child moved: \(index)")
        print("child moved: \(chat)")
        if(index == -1){
            self.chats.insert(chat, at: 0)
            self.tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
        }else{
            self.chats[index] = chat
            let chat = self.chats.remove(at: index)
            self.chats.insert(chat, at: 0)
            self.tableView.moveRow(at: IndexPath(row: index, section: 0), to: IndexPath(row: 0, section: 0))
        }
           })
}

This is my database

1 Ответ

0 голосов
/ 20 октября 2019

Проблема в том, что вы используете массив - они не могут быть переупорядочены и очень сложны для использования в базе данных NoSQL, поскольку элементы не могут быть изменены в пределах области действия массива. Обычно (почти всегда) есть гораздо лучшие варианты структурирования и хранения ваших данных.

Короче говоря, у массива в коде может быть удален индекс, а объект со следующим индексом «движется вверх» и заполняет это место,Аналогично, объекты могут быть вставлены в массив, и следующие элементы «перемещаются вниз».

Массивы в Firebase не работают таким образом;чтобы внести изменения в порядок, количество и т. д., весь массив должен быть прочитан в обновленном, а затем записан обратно - отсюда запускается множество событий, как упомянуто в моих комментариях.

См. этот устаревший, но точечный блог массивы злые и дальнейшее чтение здесь

Вы должны изменить свою структуру;

user_chats
    uid_0
       random_chat_id_0 //created with .childByAutoId
           timestamp: 20191020
           unread_messags: 3
           user_id: uid_1  //don't use -> user_name: "some username"
       random_chat_id_1
           timestamp: 20191021
           unread_messags: 3
           user_id: uid_4

.childByAutoId - ваш друг, и я обычно рекомендую использоватьэто для создания любого вида ключа узла, который должен быть уникальным.

Другое предложение - избегать имен пользователей;используйте UID пользователей. Имена пользователей часто бывают динамическими, но идентификаторы пользователей являются статическими и привязаны к этому конкретному пользователю.

Последнее;функция addChatChangeListener это не то. Есть два разных наблюдателя запросов .childChanged и .childMoved, и их функции очень разные. Я бы предложил переименовать функцию на addChatMovedLister, чтобы избежать путаницы или изменить код внутри функции для фактической обработки .childChanged событий.

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