首页 > 解决方案 > Swift Firebase - 如何向 viewDidLoad 添加观察者,在 viewDidDisappear 中将其删除,然后在 viewWillAppear 中再次读取?

问题描述

我有一个聊天日志,最初我让我的.observe( .childAdded)听众调用viewDidLoad并将其删除,viewDidDisappear但是在阅读了这个问题的评论后,我将听众移到了现在,每当我切换视图并返回时,听众都会重新运行并且我的 tableData 被填满两次获得相同的信息。在此处输入图像描述 viewWillAppear

例如。假设我在聊天中只有 1 条来自其他用户说“你好”的消息。如果聊天 vc 在 tabTwo 中,则 vc 第一次出现时代码将运行,并且 collectionView 的数据源将有 1 条消息说“你好”。如果我按下不同的选项卡并返回 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()
}

标签: iosswiftfirebasefirebase-realtime-databaseuicollectionview

解决方案


@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()
}

推荐阅读