Я загружаю некоторые данные, чтобы показать их в tableView. Я пытаюсь удалить наблюдателя для этого. Прямо сейчас наблюдатель показывает дублированный контент. Он показывает пост 10-15 раз.
Вот как я наблюдаю:
func loadData(){
let placeIdFromSearch = ViewController.placeidUebertragen
ref = Database.database().reference().child("placeID/\(placeIdFromSearch)/\(ViewComments.subComment)/subcomment/")
ref.observe(.childAdded) { (snapshot) in
print("something changed")
guard let dic = snapshot.value as? [String: Any] else { return }
let newPost = importSubPosts(dictionary: dic, key: snapshot.key)
guard let userUid = newPost.userID else { return }
self.fetchUser(uid: userUid, completed: {
self.table.insert(newPost, at: 0)
self.tableView.reloadData()
})
}
}
func fetchUser(uid: String, completed: @escaping () -> Void) {
ref = Database.database().reference().child("user").child(uid)
ref.observe(.value) { (snapshot) in
guard let dic = snapshot.value as? [String: Any] else { return }
let newUser = UserModel(dictionary: dic)
self.users.insert(newUser, at: 0)
completed()
}
}
Это должно удалить наблюдателя:
ref = Database.database().reference().child("placeID/\(placeIdFromSearch)/\(ViewComments.subComment)/subcomment/")
ref.removeAllObservers()
Но ничего не происходит.
PS: Если это поможет, если я отключу эту часть, ошибка исчезнет. Но тогда у меня нет изображения профиля пользователя. Это потому, что я уже использую эту функцию в другом tableView?
ref.observe(.value) { (snapshot) in
guard let dic = snapshot.value as? [String: Any] else { return }
let newUser = UserModel(dictionary: dic)
self.users.insert(newUser, at: 0)
Документация Firebase содержит ряд примеров того, как читать и записывать данные
В этом случае кажется, что есть пара проблем;
Один из них - как реализовать слушателей:
.childAdded — это событие запускается один раз для каждого существующего дочернего элемента и затем снова каждый раз, когда новый ребенок добавляется к указанному пути
ChildAdded отлично подходит для первоначальной загрузки списка данных, например. несколько дочерних узлов и наблюдение за дополнениями к этому списку после этого. Если вы хотите загрузить данные, а затем прекратить прослушивание, вы можете удалить прослушиватель из замыкания .childAdded (есть и другие варианты).
Если вы заинтересованы в загрузке только одного узла, «подкомментарий» см. в разделе загрузки одного узла ниже.
Если, однако, подкомментарий должен быть множественным числом «подкомментариев», потому что их несколько, вы можете использовать этот шаблон, чтобы загрузить их, не выходя из наблюдателя.
let usersRef = my_firebase.child("users")
usersRef.observeSingleEvent(by: .value, with: { snapshot in
//all users are returned to the app in the snapshot
// .value means 'give me everything in the specified node'
// so then we can iterate over the snapshot to get each users data
}
Вторая проблема, которая связана с первой проблемой в функции «fetchUser» — похоже, вы хотите прочитать одного пользователя из Firebase один раз.
Хотя вы можете использовать .observe
для этого, он фактически считывает ВСЕ данные и прослушивает все текущие события, которые не выглядят так, как вы хотите.
Лучшее решение — прочитать пользователя один раз с помощью observeSingleEvent
aka getData
, который считывает его и не оставляет слушателя, что устраняет необходимость удалять наблюдателей после завершения чтения.
В документации есть прекрасный пример того, что вы можете почти скопировать и вставить код — он читает одного пользователя и не оставляет наблюдателя. Его также можно использовать для чтения подкомментария, не оставляя слушателя привязанным. См. код на странице Однократное чтение данных
ref.child("users/\(uid)/username").getData(completion: { error, snapshot in
guard error == nil else {
print(error!.localizedDescription)
return;
}
let userName = snapshot.value as? String ?? "Unknown";
});