每次我打开ViewController时,都会获取聊天消息

时间:2019-10-09 20:23:39

标签: ios swift google-cloud-firestore

我当前正在构建一个聊天应用程序,当我单击一个用户时,它将带我到聊天记录控制器。在这里,我在viewdidload()中调用了函数fetchChatMessages(),该函数实质上是从firestore中获取会话的。问题是,每当我转到上一个控制器并再次打开聊天时,它都会再次获取消息。

不确定是从缓存还是从服务器本身获取。但是我确实在每次打印的firestore提取代码下写了一条打印语句。

现在我是新手,所以我的问题是,在其他聊天应用程序中,您可以看到似乎只是从服务器提取了一次消息,然后添加了侦听器并更新了集合视图以显示新消息。消息。就我而言,似乎一切都一遍又一遍地获取。即使我已经添加了侦听器并遵循了广受好评的教程。

此外,无论何时获取消息,我都会在底部代码中添加滚动条,因此,每次获取新消息时,控制器都会自动滚动至底部。但这每次我打开聊天时都会发生。我正在尝试修复此错误,该错误使得控制器在每次出现视图时都会不断滚动,这让我感到奇怪,打开控制器时我是否一次又一次联系firebase?

override func viewDidLoad() {
    super.viewDidLoad()

    fetchCurrentUser()
    fetchMessages()
    setupLoadView()
}

// MARK:提取消息

var listener: ListenerRegistration?

fileprivate func fetchMessages(){
    print("Fetching Messages")
    guard let cUid = Auth.auth().currentUser?.uid else {return}

    let query = Firestore.firestore().collection("matches").document(cUid).collection(connect.uid).order(by: "Timestamp")

    listener = query.addSnapshotListener { (querySnapshot, error) in
        if let error = error{
            print("There was an error fetching messages", error.localizedDescription)
            return
        }

        querySnapshot?.documentChanges.forEach({ (change) in
            if change.type == .added{
                let dictionary = change.document.data()
                self.items.append(.init(dictionary: dictionary))
                print("FIRESTORE HAS BEEN CONTACTED FETCHING MESSAGES")
            }
        })

        self.collectionView.reloadData()
        self.collectionView.scrollToItem(at: [0, self.items.count - 1], at: .bottom, animated: true)
        print("Fetched messages")
    }
}

//MARK: View Disappears

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

    if isMovingFromParent{
        listener?.remove()
    }
}

我希望控制器记住其状态。就像我滚动消息,退出控制器然后再次输入一样,它像在whatsapp中一样保持在滚动位置。

2 个答案:

答案 0 :(得分:2)

这里的问题是,每次离开屏幕时,控制器都会被释放,因为您可能将控制器推到堆栈上,然后将其弹出,这将擦除控制器的所有内部状态。这种行为确实是有意的(一旦屏幕加载,就会调用viewDidLoad)。您可以通过多种方式解决此问题。一种简单的方法是引入单例服务(在应用程序之间共享的服务),该服务包含控制器的状态,因此,每次创建控制器时,都会向服务询问其状态。请记住,这不是一个很好的解决方案,但是它应该足以作为起点。如果您需要一个示例,稍后我将相应地编辑Anwender。

答案 1 :(得分:0)

我无法就此给出确切的答案,因为它实际上取决于应用程序和服务器支持的功能,最终我将拥有某种数据库服务和聊天服务(不应通过单例访问这些服务)模式,而是通过依赖项注入)。当应获取数据时,聊天服务将定义某种策略,这意味着控制器不应意识到这一点。然后,聊天服务将通过数据库层将消息存储在一些持久性存储中,例如每个聊天的用户默认值,领域或核心数据。每次用户进入一个已经获取的聊天记录时,聊天服务都会检查是否有持久数据,如果没有,它将从服务器获取。