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