我一直在应用的聊天部分中使用“MessengerKit”。我可以从firebase编写和准备消息,但是当聊天更新时,消息将按顺序重复(一次,两次,三次等)。我将下面的chatViewController代码与应用程序上的消息视图一起附加。

chatViewController代码:

class chatViewController: MSGMessengerViewController {

    // Users in the chat
    var nameOfHirer : String = ""
    var nameofSeeker : String = ""
    var seekerData = User(displayName: "", avatar: nil, isSender: false)
    var hirerData = User(displayName: "", avatar: nil, isSender: true)

    var id = 100
    // Messages

    lazy var messages: [[MSGMessage]] = []

    func retrieveSeeker() {
        let db = Firestore.firestore()
        db.collection("Posts").document(jobID).collection("Applications").whereField("ID", isEqualTo: userID).getDocuments { (document, error) in
            for document in document!.documents {
                if error != nil {

                }else {
                    let Name = document.get("Name") as! String
                    self.nameofSeeker = Name
                    let seeker = User(displayName: Name, avatar: nil, isSender: false)
                    self.seekerData = seeker

                }
            }
        }
    }

    func retrieveHirer() {
        let db = Firestore.firestore()
        db.collection("Posts").document(jobID).getDocument { (document, error) in
            if error != nil {

            }else {
                let Hirer = document?.get("Company Name") as! String
                self.nameOfHirer = Hirer
                let hirer = User(displayName: Hirer, avatar: nil, isSender: true)
                self.hirerData = hirer
            }
        }
    }

    var uniqueID : String = ""
    var messageBody : String = ""
    var jobID : String = ""
    var userID : String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSource = self
        delegate = self
        retrieveHirer()
        retrieveSeeker()
        //        retrieveMessages()
        print(messageBody)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.tabBarController?.tabBar.isHidden = true
    }
    override var style: MSGMessengerStyle {
        var style = MessengerKit.Styles.travamigos

        style.inputPlaceholder = "Type your message here"

        return style
    }

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

        collectionView.scrollToBottom(animated: false)
    }

    override func inputViewPrimaryActionTriggered(inputView: MSGInputView) {
        id += 1
        var newMessage : String = ""
        let messageDictionary = ["Sender": userID, "MessageBody": inputView.message, "JobID": jobID]

        //        let body = MSGMessageBody.text(newMessage)
        //
        //        let message = MSGMessage(id: id, body: body, user: hirerData, sentAt: Date())

        inputView.resignFirstResponder()
        let messageDB = Database.database().reference().child("Messages").child(jobID).child(userID)
        messageDB.childByAutoId().setValue(messageDictionary) { (error, reference) in
            if error != nil {
            }else {
                retrievemess()
            }
        }

        func retrievemess() {
            let messageDB = Database.database().reference().child("Messages").child(jobID).child(userID).queryLimited(toLast: 1)
            messageDB.observe(.childAdded) { (snapshot) in
                let value = snapshot.value as? [String: AnyObject]
                let allmessage = value!["MessageBody"]
                let body = MSGMessageBody.text(allmessage as! String)
                let newmessage = MSGMessage(id: self.id, body: body, user: self.hirerData, sentAt: Date())
                self.insert(newmessage)
            }
        }
    }

    override func insert(_ message: MSGMessage) {
        collectionView.performBatchUpdates({
            if let lastSection = self.messages.last, let lastMessage = lastSection.last, lastMessage.user.displayName == message.user.displayName {
                self.messages[self.messages.count - 1].append(message)
                let sectionIndex = self.messages.count - 1
                let itemIndex = self.messages[sectionIndex].count - 1
                self.collectionView.insertItems(at: [IndexPath(item: itemIndex, section: sectionIndex)])
            } else {
                print(messages.count)
                self.messages.append([message])
                let sectionIndex = self.messages.count - 1
                self.collectionView.insertSections([sectionIndex])
            }
        }, completion: { (_) in
            self.collectionView.scrollToBottom(animated: true)
            self.collectionView.layoutTypingLabelIfNeeded()
        })
    }

    override func insert(_ messages: [MSGMessage], callback: (() -> Void)? = nil) {
        collectionView.performBatchUpdates({
            for message in messages {
                if let lastSection = self.messages.last, let lastMessage = lastSection.last, lastMessage.user.displayName == message.user.displayName {
                    self.messages[self.messages.count - 1].append(message)
                    let sectionIndex = self.messages.count - 1
                    let itemIndex = self.messages[sectionIndex].count - 1
                    self.collectionView.insertItems(at: [IndexPath(item: itemIndex, section: sectionIndex)])
                } else {
                    self.messages.append([message])
                    let sectionIndex = self.messages.count - 1
                    self.collectionView.insertSections([sectionIndex])
                }
            }
        }, completion: { (_) in

            self.collectionView.scrollToBottom(animated: false)
            self.collectionView.layoutTypingLabelIfNeeded()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                callback?()
            }
        })
    }
}

// MARK: - MSGDataSource
extension chatViewController: MSGDataSource {

    func numberOfSections() -> Int {
        return messages.count
    }

    func numberOfMessages(in section: Int) -> Int {
        return messages[section].count
    }

    func message(for indexPath: IndexPath) -> MSGMessage {
        return messages[indexPath.section][indexPath.item]
    }

    func footerTitle(for section: Int) -> String? {
        return "Just now"
    }

    func headerTitle(for section: Int) -> String? {
        return messages[section].first?.user.displayName
    }
}

// MARK: - MSGDelegate
extension chatViewController: MSGDelegate {

    func linkTapped(url: URL) {
        print("Link tapped:", url)
    }

    func avatarTapped(for user: MSGUser) {
        print("Avatar tapped:", user)
    }

    func tapReceived(for message: MSGMessage) {
        print("Tapped: ", message)
    }

    func longPressReceieved(for message: MSGMessage) {
        print("Long press:", message)
    }

    func shouldDisplaySafari(for url: URL) -> Bool {
        return true
    }

    func shouldOpen(url: URL) -> Bool {
        return true
    }
}

我正在使用的Pod是-https://github.com/steve228uk/MessengerKit
屏幕截图:

ios - CollectionView更新并在我的聊天 View 中按顺序重复。 (Swift 4.2,Xcode)(MessengerKit)-LMLPHP

最佳答案

好了,我明白了。问题是

.queryLimited(toLast: 1).observe(.childAdded)

第一次触发后会返回多个条目。解决方案是将.observe更改为.observeSingleEvent

09-04 09:30