1. 程式人生 > >Swift使用XMPPFramework做IM即時通訊的Demo

Swift使用XMPPFramework做IM即時通訊的Demo

上一篇文章處理了文字中表情的替換,現在來完成訊息的傳送功能吧(貌似前後並沒有邏輯關係哈)

首先為了測試,我們需要下載spark工具,它可以連線openfire搭建的後臺來完成即時通訊的功能,方便測試。
下載地址點這兒
博主這裡用的是Spark 2.8.3,各位可以根據自己所使用的平臺不同選擇對應的客戶端下載。由於目前只是做移動端開發,所以後臺的搭建各位可以自行google。

使用Swift連線openfire服務端,可以使用XMPPFramework框架(同android端的smack類似)。大家可以選擇手動匯入,也可以使用cocoapod匯入。博主懶,就用了cocoapod
這裡寫圖片描述

現在的XMPPFramework已經支援了Swift,所以只需在要使用的controller中匯入即可,不需要再建立橋接檔案了。

import XMPPFramework

準備工作都做得差不多了,接下來就開始真正的工作吧。

連線伺服器

/// xmpp流
var xmppStream: XMPPStream!
/// 連線伺服器
func connect() {
    if xmppStream == nil {
        xmppStream = XMPPStream()
        /// 設定代理
        xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
    }

    if
!xmppStream.isConnected() { //使用者名稱 let username = "ave2" /// 初始化一個jid,resource可以為空 let jid = XMPPJID(user: username, domain: 域名, resource: nil) xmppStream.myJID = jid do { /// 連線伺服器 try xmppStream.connect(withTimeout: 5) } catch
let error { print(error) } } }

因為我們這裡設定了代理,所以控制器需要遵循XMPPStreamDelegate協議
在連線成功後會呼叫回撥方法

/// 連線伺服器的回撥
func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
    print("連線成功")
}

登陸

我們還可以在回撥方法中輸入密碼來登陸賬號

/// 連線成功後使用密碼登陸
func xmppStreamDidConnect(_ sender: XMPPStream!) {
    print("ok")
    do {
        try sender.authenticate(withPassword: 密碼)
    } catch let error {
        print(error)
    }
}

當登陸成功後,會呼叫登陸成功的回撥方法,我們可以在登陸成功的回撥方法中設定登陸狀態

/// 使用者登陸成功
func xmppStreamDidAuthenticate(_ sender: XMPPStream!) {
    print("登陸成功")
    let presence = XMPPPresence(type: "available")
    xmppStream.send(presence)
}

使用者的登陸狀態分別有以下幾種:
available 上線
away 離開
do not disturb 忙碌
unavailable 下線

退出

既然有登陸,那我們就需要實現退出功能

/// 退出登陸並斷開連線
@objc func disconnect() {
    let presence = XMPPPresence(type: "unavailable")
    xmppStream.send(presence)
    ///斷開連線
    xmppStream.disconnect()
}

設定退出很簡單,我們只需要把狀態設定為下線即可,大家也可以不用在這個方法中設定斷開連線,畢竟我們有時退出是為了更換賬號呢(這裡只是為了方便演示)
同樣,退出也有回撥方法

/// 退出登陸的回撥
func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!) {
    print("退出成功")
}

接收訊息

有了登陸和退出功能,現在就是訊息的接收和傳送了,因為接收訊息比較簡單,所以我們就先說明接收訊息的方法吧。

/// 成功接收訊息
func xmppStream(_ sender: XMPPStream!, didReceive message: XMPPMessage!) {
    let text = message.body()
    if text != nil {
        label.text = text
    }
}

接收的訊息預設都存在message的body方法當中,我們只需要取出,然後對其進行相應的操作即可。奇怪的是,傳送一條訊息,這個接收訊息的回撥方法會呼叫三次,第一次和第三次會輸出nil,只有第二次輸出的才是有訊息的內容,各位可以嘗試列印輸出。

傳送訊息

最後來實現傳送訊息吧,
因為傳送訊息需要指定傳送的物件,我們這裡就指定私聊的名為ave1的使用者吧

/// 傳送訊息
@objc func send() {
    print("傳送訊息")
    ///建立目的使用者的jid
    let jid = XMPPJID(user: "ave1", domain: 域名, resource: nil)
    ///建立訊息
    let message = XMPPMessage(type: "chat", to: jid)
    ///新增訊息內容
    message?.addBody("hello")
    ///傳送訊息
    xmppStream.send(message)
}

在成功傳送訊息之後,同樣也有一個回撥方法

/// 成功傳送訊息
func xmppStream(_ sender: XMPPStream!, didSend message: XMPPMessage!) {
    print("成功傳送訊息 \(message.body())")
}

對了,到此就完成了一個最最簡單的使用基於openfire的XMPPFramework框架的IM即時通訊功能了。
如果還想了解更多,可以欣賞一下這位CSDN小夥伴寫的文章

最後,還是貼一下演示效果和所有的程式碼吧

這裡寫圖片描述
這裡寫圖片描述

在這裡呢,博主隨便搭了一個簡單的介面來演示效果(最上的label顯示接收到的訊息,左邊的傳送按鈕傳送訊息–每次都是傳送hello,右邊的退出按鈕退出登入並斷開連線)

這裡是所有的程式碼

import UIKit
import XMPPFramework

class ViewController: UIViewController {

    /// 接收訊息的標籤
    var label: UILabel!
    /// xmpp流
    var xmppStream: XMPPStream!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        setup()
        connect()
    }

    /// 連線伺服器
    func connect() {
        if xmppStream == nil {
            xmppStream = XMPPStream()
            /// 設定代理
            xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
        }

        if !xmppStream.isConnected() {
            //使用者名稱
            let username = "ave2"
            /// 初始化一個jid,resource可以為空
            let jid = XMPPJID(user: username, domain: 域名, resource: nil)
            xmppStream.myJID = jid
            do {
                /// 連線伺服器
                try xmppStream.connect(withTimeout: 5)
            } catch let error {
                print(error)
            }
        }

    }

    /// 退出登陸並斷開連線
    @objc func disconnect() {
        let presence = XMPPPresence(type: "unavailable")
        xmppStream.send(presence)

        xmppStream.disconnect()
    }

    /// 構建介面
    func setup() {
        label = UILabel(frame: CGRect(x: 100, y: 50, width: 200, height: 500))
        label.textColor = UIColor.black
        label.text = "hello"
        label.textAlignment = .center
        label.layer.borderWidth = 1
        label.numberOfLines = 0
        self.view.addSubview(label)

        let button = UIButton(frame: CGRect(x: 100, y: 600, width: 90, height: 44))
        button.setTitle("傳送", for: .normal)
        button.setTitleColor(UIColor.black, for: .normal)
        button.layer.borderWidth = 1
        button.addTarget(self, action: #selector(send), for: .touchUpInside)
        self.view.addSubview(button)

        let button1 = UIButton(frame: CGRect(x: 210, y: 600, width: 90, height: 44))
        button1.setTitle("退出", for: .normal)
        button1.setTitleColor(UIColor.black, for: .normal)
        button1.layer.borderWidth = 1
        button1.addTarget(self, action: #selector(disconnect), for: .touchUpInside)
        self.view.addSubview(button1)

    }

    /// 傳送訊息
    @objc func send() {
        print("傳送訊息")
        ///建立目的使用者的jid
        let jid = XMPPJID(user: "ave1", domain: 域名, resource: nil)
        ///建立訊息
        let message = XMPPMessage(type: "chat", to: jid)
        ///新增訊息內容
        message?.addBody("hello")
        ///傳送訊息
        xmppStream.send(message)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension ViewController: XMPPStreamDelegate {
    /// 連線伺服器的回撥
    func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
        print("連線成功")
    }

    /// 連線成功後使用密碼登陸
    func xmppStreamDidConnect(_ sender: XMPPStream!) {
        print("ok")
        do {
            try sender.authenticate(withPassword: 密碼)
        } catch let error {
            print(error)
        }
    }

    /// 使用者登陸成功
    func xmppStreamDidAuthenticate(_ sender: XMPPStream!) {
        print("登陸成功")
        let presence = XMPPPresence(type: "available")
        xmppStream.send(presence)
    }

    /// 退出登陸的回撥
    func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!) {
        print("退出成功")
    }

    /// 成功接收訊息
    func xmppStream(_ sender: XMPPStream!, didReceive message: XMPPMessage!) {
        let text = message.body()
        if text != nil {
            label.text = text
        }
    }

    /// 成功傳送訊息
    func xmppStream(_ sender: XMPPStream!, didSend message: XMPPMessage!) {
        print("成功傳送訊息 \(message.body())")
    }
}