我有一个聊天记录,最初在.observe( .childAdded)中调用了我的viewDidLoad侦听器,并在viewDidDisappear中将其删除了,但是在阅读了此注释ios - Swift Firebase-如何将观察者添加到viewDidLoad中,如何在viewDidDisappear中将其删除,然后在viewWillAppear中再次读取它?-LMLPHP from this question之后,我将侦听器移到了viewWillAppear,现在无论何时切换视图并返回,侦听器将再次运行,并且我的tableData被两次填充相同的信息。

例如。说我在聊天中只有一个来自其他用户的消息,说“你好”。如果chat vc在tabTwo中,则vc第一次出现时,该代码将运行,并且collectionView的数据源将显示1条消息“ hello”。如果我按一个不同的选项卡并返回tabTwo,现在将有2条消息说“你好”(相同的确切消息),因为代码再次遍历了。如果有100条消息,这将成为一个严重的问题。这意味着将有200条消息,并且每次我切换标签并返回时它将不断增加。

我还应该在删除观察者时清除tableData并在viewDidDisappear中重新加载collectionView,这样在再次调用viewWillAppear时不会重复所有数据吗?这就是我为解决此问题所做的事情,但这似乎并不正确。

有没有更好的方法可以在viewDidLoad中调用观察者,然后在viewWillAppear中再次读取它,而不会导致我的collectionView复制数据?

let currentUserId = Auth.auth().currentUser?.uid!
let toId = "theOtherUsersId"

var tableData = [Message]()
let ref = Database.database().reference().child("messageIds")

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

    ref.child(currentUserId).child(toId).observe( .childAdded, with: { [weak self] (snapshot) in

        let messageId = snapshot.key

        self?.getMessagesWith(messageId)
    })
}

func getMessagesWith(_ messageId: String) {

    Database.database().reference().child("messages").child(messageId).observeSingleEvent(of: .value, with: { [weak self] (snapshot) in

        guard let dict = snapshot.value as? [String: Any] else { return }

        let message = Message(dict: dict)

        self?.tableData.append(message)
        self?.collectionView.reloadData()
    })
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    tableData.removeAll() // something seems wrong about doing this
    collectionView.reloadData()
    ref.removeAllObservers()
}

最佳答案

我原来的回答下的@GaloTorresSevilla评论是正确的。他建议将观察者移动到viewWillAppear并仅使用messageId过滤掉tableData中已经存在的任何消息。他是100%正确的,因为当我切换回标签页时,没有数据重复

let currentUserId = Auth.auth().currentUser?.uid!
let toId = "theOtherUsersId"

var tableData = [Message]()
let ref = Database.database().reference().child("messageIds")

override func viewDidLoad() {
    super.viewDidLoad()
    // nothing to do here
}

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

    ref.child(currentUserId).child(toId).observe( .childAdded, with: { [weak self] (snapshot) in

        let messageId = snapshot.key

        // in viewWillAppear if the tableData contains the messageId above then return
        if self.tableData.contains (where: { $0.messageId ?? “” == messageId }) {
            return
        }
        self?.getMessagesWith(messageId)
    })
}

func getMessagesWith(_ messageId: String) {

    Database.database().reference().child("messages").child(messageId).observeSingleEvent(of: .value, with: { [weak self] (snapshot) in

        guard let dict = snapshot.value as? [String: Any] else { return }

        let message = Message(dict: dict)

        self?.tableData.append(message)
        self?.collectionView.reloadData()
    })
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    ref.child(currentUserId).child(toId).removeAllObservers()
}

关于ios - Swift Firebase-如何将观察者添加到viewDidLoad中,如何在viewDidDisappear中将其删除,然后在viewWillAppear中再次读取它?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55676592/

10-10 20:53