Firebase removeAllObservers()在切换视图-Swift2 iOS时不断调用

时间:2016-09-27 07:09:37

标签: ios swift firebase firebase-realtime-database observers

我读了关于这个问题的其他堆栈溢出q& a但它似乎是一个tabBarController问题,我还没有发现任何问题。

我有一个带有3个标签的tabBarController。 tab1是我成功将信息发送到Firebase的地方。在tab2中,我有tableView,它成功地从tab1读取数据。

在tab2中,我的监听器位于viewWillAppear中。我在viewDidDisappear中删除了监听器(我也试过了viewWillDisappear),这里的某个地方就是问题所在。

export default class QueryController {
    private datasets: Datasets = null; 

    constructor(datasets: Datasets) {
        this.datasets = datasets;
}

一旦我从tab2切换到任何其他选项卡,第二个我回到tab2表数据加倍,然后如果我再次切换标签并返回三倍等我尝试在viewDidLoad中设置监听器,这会阻止表数据从我切换标签时复制,但是当我从tab1发送新信息时,信息永远不会在tab2中更新。

根据Firebase文档以及我在stackoverflow / google上阅读的其他内容,应该在viewWillAppear中设置侦听器并在viewDidDisappear中删除。

关于如何在标签之间切换时防止我的数据重复的任何想法?

TAB1

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

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

tab3什么都不做。我只是将它用作备用标签来与

来回切换

3 个答案:

答案 0 :(得分:2)

removeAllObservers方法正常运行。您目前遇到的问题是由于细微遗漏:您永远不会清除 sneakerArray的内容。

注意:事件回调中不需要dispatch_async。 Firebase SDK在主队列上调用此函数。

答案 1 :(得分:1)

官方接受的答案由@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闲置频道,这就是我发布这个问题的地方,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)
}

答案 2 :(得分:0)

感谢您提出这个问题。

我过去也遇到过同样的问题。我已经解决了这个问题,如下所示。

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.