如何重新加载UITableView而不打印两次数据?

时间:2016-09-13 01:56:13

标签: swift uitableview firebase-realtime-database state observers

我有一个SlackTextViewController的视图,它可以作为UITableView使用。我在"州之间转换"使用公共String,允许它读取某个状态的1组数据和另一个状态的另一组数据。问题是当我来回切换到原始状态时,它会打印数据2,3,4次;和我一样来回走动。我从Firebase服务器加载数据,我认为这可能是Firebase问题。这是我的代码......

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if chatState == "ALL"
    {
        self.globalChat()
    }else if chatState == "LOCAL"
    {
        self.localChat()
    }
}

override func viewDidDisappear(animated: Bool) {
    self.messageModels.removeAll()
    tableView.reloadData()
    ref.removeAllObservers()
}

func chatACTN()
{
    if chatState == "ALL"
    {
        self.viewWillAppear(true)

    }else if chatState == "LOCAL"
    {
        self.viewWillAppear(true)
    }
}

func globalChat()
{
    self.messageModels.removeAll()
    tableView.reloadData()

    let globalRef = ref.child("messages")
    globalRef.keepSynced(true)
    globalRef.queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
        if snapshot.exists()
        {
            let names = snapshot.value!["name"] as! String
            let bodies = snapshot.value!["body"] as! String
            let avatars = snapshot.value!["photo"] as! String
            let time = snapshot.value!["time"] as! Int

            let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
            self.messageModels.append(messageModel)
            self.messageModels.sortInPlace{ $0.date > $1.date }
        }
        self.tableView.reloadData()
    })
}

func localChat()
{
    self.messageModels.removeAll()
    tableView.reloadData()

    print("LOCAL")
}

1 个答案:

答案 0 :(得分:2)

问题在于,每次拨打globalChat()时,您都会创建另一个新的观察者,导致多个观察者将相同的项目添加到self.messageModels。这就是为什么你在切换到全局状态时多次看到数据的原因。

由于您希望每次切换到全局时清除聊天并加载最后100个,因此当您切换到"本地"时,没有必要保持观察者处于活动状态。

当您切换到Local时,只需删除观察者即可解决问题。

来自firebase文档:

  

- (void)removeAllObservers

     

删除当前引用的所有观察者,但不会删除子引用处的任何观察者。

     

必须为每个建立侦听器的子引用再次调用removeAllObservers以删除观察者。

因此,ref.removeAllObservers()不会删除ref.child("messages")级别的观察者。

ref.child("messages").removeAllObservers函数的开头使用localChat删除您在globalChat中创建的观察者,如果你只是在这个级别处理这一个观察者,那就没问题了如果您在同一级别上有更多或者您认为将来可能添加更多,那么最好和最安全的方法是删除您创建的特定观察者。为此,您应该使用从启动观察者返回的句柄。像这样修改你的代码:

var globalChatHandle : FIRDatabaseHandle?

func globalChat()
{
    self.messageModels.removeAll()
    tableView.reloadData()

    ref.child("messages").keepSynced(true)
    globalChatHandle = ref.child("messages").queryLimitedToLast(100).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
        if snapshot.exists()
        {
            let names = snapshot.value!["name"] as! String
            let bodies = snapshot.value!["body"] as! String
            let avatars = snapshot.value!["photo"] as! String
            let time = snapshot.value!["time"] as! Int

            let messageModel = MessageModel(name: names, body: bodies, avatar: avatars, date: time)
            self.messageModels.append(messageModel)
            self.messageModels.sortInPlace{ $0.date > $1.date }
        }
        self.tableView.reloadData()
    })
}

func localChat()
{
    if globalChatHandle != nil {
        ref.child("messages").removeObserverWithHandle(globalChatHandle)
    }

    self.messageModels.removeAll()
    tableView.reloadData()

    print("LOCAL")
}

viewDidDisappear方法中替换此

ref.removeAllObservers()

ref.child("messages").removeAllObservers()