每次打开聊天屏幕时,都从xmpp中的脱机数据库获取重复消息吗?

时间:2019-06-30 09:09:44

标签: ios swift xmpp

我正在尝试从离线数据库中获取群聊离线消息。但是,当我尝试获取消息时,然后多次获取重复的消息。我不知道如何解决这个问题。请帮助我解决此问题。

我附上了XMPP实现的代码。...

这是我的XMPPController类,可以在其中使用服务器设置客户端。

class XMPPController: NSObject {

    var xmppStream: XMPPStream

    let hostName: String
    let userJID: XMPPJID
    let hostPort: UInt16
    let password: String

    var xmppStorage: XMPPMessageArchivingCoreDataStorage?
    var messageArchiving: XMPPMessageArchiving?

    init(hostName: String, userJIDString: String, hostPort: UInt16 = 5222, password: String) throws {
        guard let userJID = XMPPJID(string: userJIDString) else {
            throw XMPPControllerError.wrongUserJID
        }

        self.hostName = hostName
        self.userJID = userJID
        self.hostPort = hostPort
        self.password = password

        // Stream Configuration
        self.xmppStream = XMPPStream()
        self.xmppStream.hostName = hostName
        self.xmppStream.hostPort = hostPort
        self.xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicy.allowed
        self.xmppStream.myJID = userJID

        super.init()
        self.xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
        xmppStorage = XMPPMessageArchivingCoreDataStorage()
        messageArchiving = XMPPMessageArchiving(messageArchivingStorage: xmppStorage)
        messageArchiving?.clientSideMessageArchivingOnly = false
        messageArchiving?.activate(xmppStream)
        messageArchiving?.addDelegate(self, delegateQueue: DispatchQueue.main)
    }

    func connect() {
        if !self.xmppStream.isDisconnected {
            return
        }
        try! self.xmppStream.connect(withTimeout: XMPPStreamTimeoutNone)
    }
}

extension XMPPController: XMPPStreamDelegate {

    func xmppStreamDidConnect(_ stream: XMPPStream) {
        print("Stream: Connected")
        try! stream.authenticate(withPassword: self.password)
    }

    func xmppStreamDidAuthenticate(_ sender: XMPPStream) {
        self.xmppStream.send(XMPPPresence())
        print("Stream: Authenticated")
    }

    func xmppStream(_ sender: XMPPStream, didReceive message: XMPPMessage) {
        print("Message XMPPController Called")
    }
}

这是我的ViewController类实现。在这种情况下,我们可以创建和加入聊天室并分组发送消息。

class GroupMessagesViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var inputTextField: UITextField!
    @IBOutlet weak var photosButton: UIPhotosButton!

    var xmppController: XMPPController!
    var messages = [Message]()
    var xmppRoom: XMPPRoom!
    var isXMPPRoomDidReceiveMsgCalled = false

    override func viewDidLoad() {
        super.viewDidLoad()

        // Group Chat
        self.createOrJoinRoom()
    }

    deinit {
        xmppRoom.deactivate()
        xmppRoom.removeDelegate(self)
        xmppRoom = nil
    }


    func retrieveGroupMessagesFromOfflineDb() {
        let fetchRequest = NSFetchRequest<XMPPMessageArchiving_Message_CoreDataObject>(entityName: "XMPPMessageArchiving_Message_CoreDataObject")
        fetchRequest.returnsDistinctResults = true

//        let predicate = NSPredicate(format: "bareJidStr == %@", "groupdemo@conference.chat.webolutionit.co.uk")
//        fetchRequest.predicate = predicate

        let predicate = NSPredicate(format: "messageStr CONTAINS[cd] %@ AND bareJidStr == %@", "groupchat", "groupdemo@conference.\(XMPPKeys.host)")
        fetchRequest.predicate = predicate

        let context = xmppController.xmppStorage?.mainThreadManagedObjectContext

        do {
            let messageHistoryArray = try context?.fetch(fetchRequest)

            if messageHistoryArray?.count != 0 {
                self.messages.removeAll()
                messageHistoryArray?.forEach({ (msg) in
                    var message: Message!

                    if msg.body.contains(".jpg") {
                        message = Message(message: msg.body, from: msg.message.fromStr, to: msg.message.toStr, type: msg.message.type, contentType: .photo)
                    }
                    else {
                        message = Message(message: msg.body, from: msg.message.fromStr, to: msg.message.toStr, type: msg.message.type, contentType: .text)
                    }

                    self.messages.append(message)
                })
                isXMPPRoomDidReceiveMsgCalled = true
                self.tableView.reloadData()
                tableView.scrollToBottom()
            }
        }
        catch {
            isXMPPRoomDidReceiveMsgCalled = true
            print(error.localizedDescription)
        }
    }

    func createOrJoinRoom() {
        let roomStorage = XMPPRoomMemoryStorage()
        let roomId = XMPPJID(string: "groupdemo@conference.\(XMPPKeys.host)")
        xmppRoom = XMPPRoom(roomStorage: roomStorage!, jid: roomId!, dispatchQueue: DispatchQueue.main)

        let userId = XMPPJID(string: "testUser@chat.\(XMPPKeys.receiverJID)")
        xmppRoom.inviteUser(userId!, withMessage: "Join Please")

        xmppRoom.activate(xmppController.xmppStream)
        xmppRoom.addDelegate(self, delegateQueue: DispatchQueue.main)
        xmppRoom.join(usingNickname: XMPPKeys.senderJID, history: nil, password: nil)
    }

    // MARK:- IBACTIONS
    @IBAction func backBtnPressed(_ sender: UIButton) {
        _ = self.navigationController?.popViewController(animated: true)
    }

    @IBAction func sendBtnPressed(_ sender: UIButton) {
        if let text = inputTextField.text {
            if text != "" {

                let message = XMLElement.element(withName: "message") as! XMLElement
                message.addAttribute(withName: "from", stringValue: XMPPKeys.senderJID)
                message.addAttribute(withName: "to", stringValue: "groupdemo@conference.\(XMPPKeys.host)")
                message.addAttribute(withName: "type", stringValue: "groupchat")
                message.addAttribute(withName: "id", stringValue: xmppController.xmppStream.generateUUID)
                let uuid = UIDevice.current.identifierForVendor?.uuidString
                message.addAttribute(withName: "uuid", stringValue: uuid.leoSafe())

                let body = XMLElement.element(withName: "body") as! XMLElement
                body.stringValue = text
                message.addChild(body)

                xmppController.xmppStream.send(message)
            }
        }
    }

}


//MARK: UITableView Delegate & DataSource
extension GroupMessagesViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        print(messages.count)
        return messages.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let message = messages[indexPath.row]
        let currentUser = message.to.leoSafe().components(separatedBy: "/")[0]

        if message.contentType == .text {
            let cell = tableView.dequeueReusableCell(withIdentifier: XMPPKeys.senderJID.contains(currentUser) ? "MessageTableViewCell" : "UserMessageTableViewCell") as! MessageTableViewCell
            cell.set(message)
            return cell
        }
        let cell = tableView.dequeueReusableCell(withIdentifier: currentUser == XMPPKeys.senderJID ? "MessageAttachmentTableViewCell" : "UserMessageAttachmentTableViewCell") as! MessageAttachmentTableViewCell
        cell.delegate = self
        cell.set(message)
        return cell
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        guard tableView.isDragging else { return }
        cell.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
        UIView.animate(withDuration: 0.3, animations: {
            cell.transform = CGAffineTransform.identity
        })
    }
}

//MARK: UItextField Delegate
extension GroupMessagesViewController: UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        return textField.resignFirstResponder()
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return true
    }
}

//MARK: MessageTableViewCellDelegate Delegate
extension GroupMessagesViewController: MessageTableViewCellDelegate {
    func messageTableViewCellUpdate() {
        tableView.beginUpdates()
        tableView.endUpdates()
    }
}

extension GroupMessagesViewController: XMPPRoomDelegate {
    func xmppRoomDidJoin(_ sender: XMPPRoom) {
        print("Room Joined")
        sender.fetchConfigurationForm()
        let a = xmppRoom.fetchMembersList()

        self.retrieveGroupMessagesFromOfflineDb()
    }

    func xmppRoomDidCreate(_ sender: XMPPRoom) {
        print("Room Created")
    }

    func xmppRoomDidLeave(_ sender: XMPPRoom) {
        print("Room Leave")
    }

    func xmppRoomDidDestroy(_ sender: XMPPRoom) {
        print("Room Destroyed")
    }

    func xmppRoom(_ sender: XMPPRoom, didReceive message: XMPPMessage, fromOccupant occupantJID: XMPPJID) {
        print("Group Message Retrieved")

        if isXMPPRoomDidReceiveMsgCalled {
            if message.isGroupChatMessageWithBody {
                var msg: Message!

                if (message.body?.contains(".jpg"))! {
                    msg = Message(message: message.body, from: message.fromStr, to: message.toStr, type: message.type!, contentType: .photo)
                }
                else {
                    msg = Message(message: message.body, from: message.fromStr, to: message.toStr, type: message.type!, contentType: .text)
                }

                self.messages.append(msg)
                self.tableView.reloadData()
                self.tableView.scrollToBottom()
                inputTextField.text = ""
            }
        }
    }

    func xmppRoom(_ sender: XMPPRoom, didFetchModeratorsList items: [Any]) {
        print(items)
    }

    func xmppRoom(_ sender: XMPPRoom, didFetchMembersList items: [Any]) {
        print(items)
    }

}

// XMPPMUCDelegate METHODS
// ACCEPTING GROUP INVITATION
extension GroupMessagesViewController: XMPPMUCDelegate {

    func xmppMUC(_ sender: XMPPMUC, roomJID: XMPPJID, didReceiveInvitation message: XMPPMessage) {
        let x = message.element(forName: "x", xmlnsPrefix: XMPPMUCUserNamespace)
        let invite = x?.elements(forName: "invite")

        if !(invite?.isEmpty)! {
            let conferenceRoomId = message.attribute(forName: "from")?.stringValue
            self.joinMultiUserChat(roomName: conferenceRoomId.leoSafe())
        }
    }

    func joinMultiUserChat(roomName: String) {
        let roomJID = XMPPJID(string: roomName)
        let xmppStorage = XMPPRoomMemoryStorage()
        xmppRoom = XMPPRoom(roomStorage: xmppStorage!, jid: roomJID!, dispatchQueue: DispatchQueue.main)
        xmppRoom.activate(xmppController.xmppStream)
        xmppRoom.addDelegate(self, delegateQueue: DispatchQueue.main)
        xmppRoom.join(usingNickname: xmppController!.xmppStream.myJID!.full, history: nil)
    }   
}

0 个答案:

没有答案