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
  • 1

准备工作都做得差不多了,接下来就开始真正的工作吧。

连接服务器

/// xmpp流
var xmppStream: XMPPStream!
  • 1
  • 2
/// 连接服务器
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)
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

因为我们这里设置了代理,所以控制器需要遵循XMPPStreamDelegate协议
在连接成功后会调用回调方法

/// 连接服务器的回调
func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
    print("连接成功")
}
  • 1
  • 2
  • 3
  • 4

登陆

我们还可以在回调方法中输入密码来登陆账号

/// 连接成功后使用密码登陆
func xmppStreamDidConnect(_ sender: XMPPStream!) {
    print("ok")
    do {
        try sender.authenticate(withPassword: 密码)
    } catch let error {
        print(error)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

当登陆成功后,会调用登陆成功的回调方法,我们可以在登陆成功的回调方法中设置登陆状态

/// 用户登陆成功
func xmppStreamDidAuthenticate(_ sender: XMPPStream!) {
    print("登陆成功")
    let presence = XMPPPresence(type: "available")
    xmppStream.send(presence)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

用户的登陆状态分别有以下几种:
available 上线
away 离开
do not disturb 忙碌
unavailable 下线

退出

既然有登陆,那我们就需要实现退出功能

/// 退出登陆并断开连接
@objc func disconnect() {
    let presence = XMPPPresence(type: "unavailable")
    xmppStream.send(presence)
    ///断开连接
    xmppStream.disconnect()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

设置退出很简单,我们只需要把状态设置为下线即可,大家也可以不用在这个方法中设置断开连接,毕竟我们有时退出是为了更换账号呢(这里只是为了方便演示)
同样,退出也有回调方法

/// 退出登陆的回调
func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!) {
    print("退出成功")
}
  • 1
  • 2
  • 3
  • 4

接收消息

有了登陆和退出功能,现在就是消息的接收和发送了,因为接收消息比较简单,所以我们就先说明接收消息的方法吧。

/// 成功接收消息
func xmppStream(_ sender: XMPPStream!, didReceive message: XMPPMessage!) {
    let text = message.body()
    if text != nil {
        label.text = text
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接收的消息默认都存在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)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在成功发送消息之后,同样也有一个回调方法

/// 成功发送消息
func xmppStream(_ sender: XMPPStream!, didSend message: XMPPMessage!) {
    print("成功发送消息 \(message.body())")
}
  • 1
  • 2
  • 3
  • 4

对了,到此就完成了一个最最简单的使用基于openfire的XMPPFramework框架的IM即时通信功能了。
如果还想了解更多,可以欣赏一下这位CSDN小伙伴写的文章


最后,还是贴一下演示效果和所有的代码吧

Swift使用XMPPFramework做IM即时通信的Demo_第1张图片
Swift使用XMPPFramework做IM即时通信的Demo_第2张图片

在这里呢,博主随便搭了一个简单的界面来演示效果(最上的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())")
    }
}

你可能感兴趣的:(即时通讯)