Firebase removeAllObservers () продолжает делать вызовы при переключении просмотров -Swift2 iOS

Я прочитал другой переполнение стека q & a об этой проблеме, но, похоже, проблема с tabBarController, в которой я ничего не нашел.

У меня есть tabBarController с 3 вкладками. tab1 – это место, где я успешно отправляю информацию в Firebase. В tab2 у меня есть tableView, который успешно считывает данные из tab1.

В tab2 мой слушатель находится в viewWillAppear. Я удаляю слушателя в viewDidDisappear (я также пробовал viewWillDisappear), и где-то здесь возникает проблема.

override func viewDidDisappear(animated: Bool) { self.sneakersRef!.removeAllObservers() //When I tried using a handle in viewWillAppear and then using the handle to remove the observer it didn't work here either //sneakersRef!.removeObserverWithHandle(self.handle) } 

Как только я переключусь с tab2 на любую другую вкладку, второй вернусь к tab2, данные таблицы удваиваются, а затем, если я снова переключу вкладки и вернусь, это утроится и т. Д. Я попытался настроить прослушиватель внутри viewDidLoad, который предотвращает дублирование данных таблицы, когда Я переключаю вкладки, но когда я отправляю новую информацию с tab1, информация никогда не обновляется в tab2.

Согласно документам Firebase и почти всему, что я читал в stackoverflow / google, слушатель должен быть установлен в viewWillAppear и удален в viewDidDisappear.

Любые идеи о том, как предотвратить дублирование моих данных, когда я переключаюсь между вкладками?

tab1

 import UIKit import Firebase import FirebaseAuth import FirebaseDatabase class TabOneController: UIViewController{ var ref:FIRDatabaseReference! @IBOutlet weak var sneakerNameTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() self.ref = FIRDatabase.database().reference() } @IBAction func sendButton(sender: UIButton) { let dict = ["sneakerName":self.sneakerNameTextField.text!] let usersRef = self.ref.child("users") let sneakersRef = usersRef.child("sneakers").childByAutoID() sneakersRef?.updateChildValues(dict, withCompletionBlock: {(error, user) in if error != nil{ print("\n\(error?.localizedDescription)") } }) } } 

tab2

 import UIKit import Firebase import FirebaseAuth import FirebaseDatabase class TabTwoController: UITableViewController{ @IBOutlet weak var tableView: UITableView! var handle: Uint!//If you read the comments I tried using this but nahhh didn't help var ref: FIRDatabaseReference! var sneakersRef: FIRDatabaseReference? var sneakerArray = [String]() override func viewDidLoad() { super.viewDidLoad() self.ref = FIRDatabase.database().reference() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let usersRef = self.ref.child("users") //Listener self.sneakersRef = usersRef.child("sneakers") //I tried using the handle //---self.handle = self.sneakersRef!.observeEventType(.ChildAdded... self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in if let dict = snapshot.value as? [String:AnyObject]{ let sneakerName = dict["sneakerName"] as? String self.sneakerArray.append(sneakerName) dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() }) } }), withCancelBlock: nil) } //I also tried viewWillDisappear override func viewDidDisappear(animated: Bool) { self.sneakersRef!.removeAllObservers() //When I tried using the handle to remove the observer it didn't work either //---sneakersRef!.removeObserverWithHandle(self.handle) } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.sneakerArray.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier("sneakerCell", forIndexPath: indexPath) cell.textLabel?.text = sneakerArray[indexPath.row] return cell } } 

tab3 ничего не делает. Я просто использую его как альтернативную вкладку для переключения туда и обратно с помощью

Solutions Collecting From Web of "Firebase removeAllObservers () продолжает делать вызовы при переключении просмотров -Swift2 iOS"

Метод removeAllObservers работает правильно. Проблема, которую вы сейчас испытываете, вызвана незначительной недостающей деталью: вы никогда не очищаете содержимое sneakerArray .


Примечание: во время обратного вызова события нет необходимости dispatch_async . Firebase SDK вызывает эту функцию в главной очереди.

Официальный принятый ответ был отправлен @vzsg. Я просто детализирую его для следующего человека, который сталкивается с этой проблемой. Проголосуйте за его ответ.

Что в основном происходит, когда вы используете .childAdded , Firebase петли вокруг и захватывает каждого ребенка из узла ( in my case the node is "sneakersRef" ). Firebase захватывает данные, добавляет их в массив ( in my case self.sneakerArray ), затем возвращается, чтобы получить следующий набор данных, добавляет его в массив и т. Д. Очищая массив в начале следующего цикла, после завершения FB массив будет пустым. Если вы переключаете сцены, у вас всегда будет пустой массив, и единственные данные, которые отобразит ui, – это FB, который снова зацикливает узел.

Также я избавился от вызова dispatch_async, потому что он сказал, что FB вызывает функцию в основной очереди. Я использовал только self.tableView.reloadData ()

На боковой ноте вы должны подписаться на firebase-community.slack.com. Это официальный канал Firebase Slack, и именно там я разместил этот вопрос и vzsg ответил на него.

 override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) //CLEAR THE ARRAY DATA HERE before you make your Firebase query self.sneakerArray.removeAll() let usersRef = self.ref.child("users") //Listener self.sneakersRef = usersRef.child("sneakers") //I tried using the handle //---self.handle = self.sneakersRef!.observeEventType(.ChildAdded... self.sneakersRef!.observeEventType(.ChildAdded, withBlock: {(snapshot) in if let dict = snapshot.value as? [String:AnyObject]{ let sneakerName = dict["sneakerName"] as? String self.sneakerArray.append(sneakerName) //I didn't have to use the dispatch_async here self.tableView.reloadData() } }), withCancelBlock: nil) } 

Спасибо, что задали этот вопрос.

Я также сталкивался с такой же проблемой в прошлом. Я решил эту проблему следующим образом.

1) Определите массив, содержащий список наблюдателей.

 var aryObserver = Array<Firebase>() 

2) Добавьте наблюдателя, как следует.

  self.sneakersRef = usersRef.child("sneakers") aryObserver.append( self.sneakersRef) 

3) Снимите наблюдателя, как показано ниже.

  for fireBaseRef in self.aryObserver{ fireBaseRef.removeAllObservers() } self.aryObserver.removeAll() //Remove all object from array.