1. 基本步骤:首先导入Xmpp框架,配置环境

-》由于我们使用的是OC的Xmpp框架,再进行Swift开发时需要进行桥接。 具体方法就是创建一个基于c的.h的头文件,然后将我们需要编译OC的语言的头文件包含这个.h文件中;

-》然后导入如下库文件,在头头文件选择路径中

如上图, 设置header Search paths 设置头文件的搜索路径,导入libxml2库文件相对路径,***注意前面是 usr 。以前第一次装的时候写成user找了半个多小时

-> 然后创建界面,随便弄两个框框和按钮自定义一个建议的界面。

应为在应用程序中用户名和密码可能被反复的使用,所以我们需要讲它门设置成一个单利类。

如下代码所示:

import UIKit

class WSBUserinfo: NSObject {

    // 登录的用户名密码

    var  userName : String?   

    var  userPasswd : String?

    // 注册的用户名密码

    var  userRegisterName : String?

    var  userRegisterPasswd : String?

    // 为了区分登录和注册 

    var  isLogin : Bool?

    // 单例

    class func getShareInstance() -> WSBUserinfo{

        struct Singleton {

            static var  dispatchOne : dispatch_once_t = 0

            static var  instance : WSBUserinfo? = nil

        }

        dispatch_once(&Singleton.dispatchOne) { () -> Void in

            Singleton.instance = WSBUserinfo()

        }

        return Singleton.instance!

    }

}

//由于登录流程设计到了xmpp流协议实现,步骤较多。这里我们可以单独封装一个工具类。这样我们的登录和注册的主控制器就能得到极大的解脱:

在登录控制器中我们只需要将输入框的用户输入信息赋值到单利用户信息类 UserInfo里

然后调用 单利工具类的 usrLogin()方法及可自动完成所有的登录流程

再通过指定一个协议,实现对登录和注册状态的监听;

注册控制器的逻辑同上,这里就不重复了 。

注意点1:再每次连接请求时先把之前的连接断开,这样能避免一个账号长连接而其它的账号无法连接。

注意点2:再发送登录注册时中间都涉及到了共同的连接请求和连接状态请求,我们需要在单利类中建立一个Bool属性值做分支判定,这样我们只需要在方法内部做简单的调整,从而省去大量的代码步骤。

具体步骤请看下面代码

import UIKit

class WSBLoginViewController: UIViewController,WSBXMPPLoginDelegate {

    @IBOutlet weak var userNameField: UITextField!

    @IBOutlet weak var userPasswdField: UITextField!

    @IBAction func loginBtnClick(sender: AnyObject) {

        WSBUserinfo.getShareInstance().isLogin = true

        print("用户名:\(userNameField.text!)")d

        print("密码是:\(userPasswdField.text!)")

        // 把用户名 密码存入工具类 WSBUserinfo 这个单例对象中

        WSBUserinfo.getShareInstance().userName = userNameField.text!

        WSBUserinfo.getShareInstance().userPasswd = userPasswdField.text!

        // 调用XMPP 工具类 完成登录

        // 登录之前先给WSBXMPPTool设置代理

        WSBXMPPTool.getSharedInstance().loginDelegate = self

        WSBXMPPTool.getSharedInstance().userLogin()

    }

    /** 登录协议中的方法 */

    func loginSuccess() {

        print("登录成功")

        // 切换到主界面

        let  storyBoard  = UIStoryboard.init(name: "Main", bundle: nil)

        UIApplication.sharedApplication().keyWindow?.rootViewController =

            storyBoard.instantiateInitialViewController()

    }

    func loginFailed() {

        print("登录失败")

    }

    func loginNetError() {

        print("登录时网络错误")

    }

    override func viewDidLoad() {

        super.viewDidLoad()

    }

    deinit{

        print("deinit\(self)")

    }

}

    RegisterViewController:

import UIKit

class WSBRegisterViewController: UIViewController,WSBXMPPRegisterDelegate {

    @IBOutlet weak var userRegiserName: UITextField!

    @IBOutlet weak var userRegisterPasswd: UITextField!

    @IBAction func registerBtnClick(sender: AnyObject) {

        // 说明这是注册行为

        WSBUserinfo.getShareInstance().isLogin = false

        WSBUserinfo.getShareInstance().userRegisterName = self.userRegiserName.text!

        WSBUserinfo.getShareInstance().userRegisterPasswd = self.userRegisterPasswd.text!

        // 调用XMPPTool的 注册方法

        WSBXMPPTool.getSharedInstance().registerDelegate = self

        WSBXMPPTool.getSharedInstance().userRegister()

    }

    /** 实现注册协议中的方法 */

    func registerSuccess() {

        print("注册成功")

        self.dismissViewControllerAnimated(true, completion: nil)

    }

    func registerFailed() {

        print("注册失败")

    }

    func registerNetError() {

        print("注册时网络错误")

    }

}

  登录和注册协议

import Foundation

// 登录协议 

protocol WSBXMPPLoginDelegate : NSObjectProtocol {

     // 登录成功

     func  loginSuccess()

     // 登录失败

     func  loginFailed()

    //  网络错误

     func  loginNetError()

}

// 注册协议

protocol WSBXMPPRegisterDelegate : NSObjectProtocol {

    // 注册成功

    func  registerSuccess()

    // 注册失败

    func  registerFailed()

    // 注册网络错误

    func  registerNetError()

}

Swift:

import UIKit

/** 桥接文件 项目--buildSettings --> 搜索 Objective-c Bride 设置即可

  这是一个XMPP的工具类 可以完成登录和注册的行

*/

class WSBXMPPTool: NSObject, XMPPStreamDelegate {

    var  xmppStream : XMPPStream!

    // 登录的Delegate

    weak var loginDelegate : WSBXMPPLoginDelegate?

    // 注册的Deletegate

    weak var registerDelegate : WSBXMPPRegisterDelegate?

    // 保证xmppStream 使用时非空

    override init() {

        super.init()

        setupXmppStream()

    }

    class func  getSharedInstance() -> WSBXMPPTool {

        struct Singleton {

            static var predicate : dispatch_once_t = 0

            static var instance : WSBXMPPTool? = nil

        }

        dispatch_once(&Singleton.predicate) { () -> Void in

            Singleton.instance = WSBXMPPTool()

        }

        return  Singleton.instance!

    }

    // 设置流 设置代理

    func setupXmppStream(){

        xmppStream = XMPPStream()

        xmppStream.addDelegate(self, delegateQueue: dispatch_get_main_queue())

    }

    // 连接服务器

    func connectToHost(){

        // 先断开上次的 不断开登录之后没法再登录

        xmppStream.disconnect();

        // 调用设置xmppStream 

        if self.xmppStream == nil {

           self.setupXmppStream()

        }

        var userName : String? = nil

        if WSBUserinfo.getShareInstance().isLogin! {

            userName = WSBUserinfo.getShareInstance().userName

        }else{

            userName = WSBUserinfo.getShareInstance().userRegisterName

        }

        // 构建jid   设置hostName 和 port 

        xmppStream.myJID = XMPPJID.jidWithUser(userName, domain: XMPPDOMAIN, resource: "iphone")

        xmppStream.hostName = XMPPHOSTNAME

        xmppStream.hostPort = XMPPPORT

        do {

            try xmppStream.connectWithTimeout(XMPPStreamTimeoutNone)

        }catch let error as NSError{

            print(error.description)

        }

    }

    // 连接成功(代理方法)

    func xmppStreamDidConnect(sender: XMPPStream!) {

        // 调用发送密码 请求授权

        if WSBUserinfo.getShareInstance().isLogin!{

            self.sendLoginPasswd()

        }else{

            // 使用密码注册

            self.sendRegisterPasswd()

        }

    }

    // 发送密码 注册

    func sendRegisterPasswd(){

        do{

            try xmppStream.registerWithPassword(WSBUserinfo.getShareInstance().userRegisterPasswd)

        }catch let error as NSError{

            print(error.description)

        }

    }

    // 发送密码 请求授权

    func sendLoginPasswd(){

        do{

         try xmppStream.authenticateWithPassword(WSBUserinfo.getShareInstance().userPasswd)

        }catch let error as NSError{

             print(error.description)

        }

    }

    // 授权成功(代理方法)

    func xmppStreamDidAuthenticate(sender: XMPPStream!) {

        print("授权成功")

        // 发送在线消息

        self.sendOnLine()

        // 调用代理的登录成功的方法

        loginDelegate?.loginSuccess()

    }

    // 发送在线消息

    func sendOnLine(){

      xmppStream.sendElement(XMPPPresence())

    }

    // 授权失败

    func xmppStream(sender: XMPPStream!, didNotAuthenticate error: DDXMLElement!) {

        print(error.description)

        // 授权失败 调用代理的登录失败的方法

        loginDelegate?.loginFailed()

    }

    // 连接断开(代理方法)

    func xmppStreamDidDisconnect(sender: XMPPStream!, withError error: NSError!) {

        // 如果网络有问题断开 则error 中有值

        // 如果是主动断开  则error是 nil

        if error != nil {

            if WSBUserinfo.getShareInstance().isLogin!{

              //登录网络有问题 调用代理的网络错误

            loginDelegate?.loginNetError()

            }else{

                // 注册时网络有问题

                registerDelegate?.registerNetError()

            }

        }

    }

    //注册成功 (代理方法 )

    func  xmppStreamDidRegister(sender: XMPPStream!) {

        // 调用代理的注册成功

        registerDelegate?.registerSuccess()

    }

    // 注册失败 (代理方法 )

    func xmppStream(sender: XMPPStream!, didNotRegister error: DDXMLElement!) {

        registerDelegate?.registerFailed()

    }

    // 用户完成登录的方法

    func  userLogin(){

        self.connectToHost()

    }

    // 用户完成注册的方法

    func  userRegister(){

        self.connectToHost()

    }

}

总的来说基本思路和OC的写法基本相同,下面简但介绍下程序的设计思路。

一 总体登录流程:

1.设置xmpp流配置(port id domain)-》2. 请求链接绑定jid-》3.监听链接是否成功-》4.成功则发送密码请求授权-》5.监听授权是成功-》6.授权成功则发送出席状态。

注册流程:

1.设置xmpp流配置(port id domain)-》 2.请求链接绑定jid-》3.监听链接是否成功-》4.成功则发送密码请求注册-》5.监听注册是否成功-》6.注册成功则返回登录界面。

从上面可以看出登录和注册的基本流程大致相同,只不郭仔第4步骤中调用的方法不通而已,为了操作方便我们定义了一个Bool值,在第3部链接成功中进行选择判定 isRegister。

其余对应的方法不通的地方也依次使用Bool选择判定。

二 .协议的使用时机。

我们将此6部只需要封装到一个方法里,并返回一个结果(链接是否成功,授权是否成功)    usrLogin:(返回的结果)。  这样我们在主控制器中通过调用xmppTool单利类的方法就能够拿到这个结果。

在上面链接是否成功,是否授权,是否注册成功,一共5处需传递给主控制器。  这里可以使用协议或者代理,当然还有通知.

下面就种方式常用的方式代理和闭包(其实就相当于OC的Block回调,变了个说法而已)

****协议的写法和OC大不相同,值得注意的是,我们定义的协议前面一定要继承系统的NSObjectProtocol(这是因为我们在定义var delegate:Protococl! 的时候,前面不能使用weak,但是不使用weak又会导致设置协议后造成另一个对象强强引用释放不了,所以此处需要继承下系统的协议,具体什么原因楼主目前暂时也还没有弄明白)。

其它的只是变了个写法格式,看代码就可以了,逻辑完全没变。

三. 使用Block代替上面的协议。

3.1 这里我们首先定义一个枚举类型,用于定义回调传值的类型,然后再定义一个闭包类型。

enum XMPPResultType{
case XMPPResultTypeRegisterSuccess,
XMPPResultTypeRegisterFailed,
XMPPResultTypeRegisterNetError
}
typealias RegisterCloserType = (result : XMPPResultType) -> Void

3.2 接着在XmppTool工具类中定义一个闭包类型,用来接收注册或者登陆控制器中传来的闭包函数

    weak var loginDelegate : WSBXMPPLoginDelegate?
// 保存传入的闭包
var registerCloser : RegisterCloserType!

3.3 调用闭包方法

    /* 用户完成注册的方法 当用闭包时 需要让调用者传入一个闭包来获取注册状态  */
func userRegister(function : RegisterCloserType!){
registerCloser = function
self.connectToHost()
}

3.4在XmppTool工具类中需要使用回调的地方执行次闭包函数,下面以其中一个为例, 网络连接错误,注册成功,失败,这三处都需要调用。

 registerCloser!(result: XMPPResultType.XMPPResultTypeRegisterSuccess)

3.5 我们在主控制器中只需要拿出闭包函数的result的状态及可判断是否  后台执行的结果.注意需要使用weakself,否则无法释放。

 weak var weakVc = self
WSBXMPPTool.getSharedInstance().userRegister { (result) -> Void in
switch result{
case .XMPPResultTypeRegisterSuccess:
print("注册成功")
weakVc?.dismissViewControllerAnimated(true, completion: nil)
case .XMPPResultTypeRegisterFailed:
print("注册失败")
case .XMPPResultTypeRegisterNetError:
print("网络错误")
} } }

7. Swift 基于Xmpp和openfire实现一个简单的登录注册的更多相关文章

  1. go语言实现一个简单的登录注册web小程序

    最近学习golang也有一段时间了,基础差不多学了个大概,因为本人是java程序员,所以对web更感兴趣.根据<go web编程>中的例子改编一个更简单的例子,供新手参考,废话不多说,上菜 ...

  2. Android基于XMPP Smack openfire 开发的聊天室

    Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...

  3. (转)微服务_创建一个简单的Eureka注册中心

    原文地址:https://www.cnblogs.com/lplshermie/p/9105329.html 微服务和分布式已经成了一种极其普遍的技术,为了跟上时代的步伐,最近开始着手学习Spring ...

  4. 创建一个简单的Eureka注册中心

    微服务和分布式已经成了一种极其普遍的技术,为了跟上时代的步伐,最近开始着手学习SpringCloud,就从Eureka开始.他们俩就不做介绍了,网上的说明一堆,随便打开一个搜索引擎输入关键字都足够了解 ...

  5. 基于Spring aop写的一个简单的耗时监控

    前言:毕业后应该有一两年没有好好的更新博客了,回头看看自己这一年,似乎少了太多的沉淀了.让自己做一个爱分享的人,好的知识点拿出来和大家一起分享,一起学习. 背景: 在做项目的时候,大家肯定都遇到对一些 ...

  6. 基于gin框架搭建的一个简单的web服务

    刚把go编程基础知识学习完了,学习的时间很短,可能还有的没有完全吸收.不过还是在项目中发现知识,然后在去回顾已学的知识,现在利用gin这个web框架做一个简单的CRUD操作. 1.Go Web框架的技 ...

  7. 基于 Vue + Koa2 + MongoDB + Redis 实现一个完整的登录注册

    项目地址:https://github.com/caochangkui/vue-element-responsive-demo/tree/login-register 通过 vue-cli3.0 + ...

  8. javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册

    一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp ...

  9. jmeter 压力测试(一)一个简单的登录

    写在最前面,之所以记录这个最最简单的http的登录,是因为捣鼓了一天,真的是找错也找不错了,后来请教的同事,重新写了一个ok了,最后发现竟然是因为[http信息头]写的有问题,简直是!!醉了 如下,这 ...

随机推荐

  1. Linux 下应用程序最大打开文件数的理解和修改

    运行在Linux系统上的Java程序运行了一段时间后出现"Too many open files"的异常情况. 这种情况常见于高并发访问文件系统,多线程网络连接等场景.程序经常访问 ...

  2. iOS经典面试题总结--内存管理

    iOS经典面试题总结--内存管理 内存管理 1.什么是ARC? ARC是automatic reference counting自动引用计数,在程序编译时自动加入retain/release.在对象被 ...

  3. python的__future__特性

    使用python的__future__特性, __future__是在旧版本的python中提供了新版python的特性. 1) 在python2中相除返回浮点数,在python3中默认返回浮点数 & ...

  4. 1.3 第一个C#程序

    几乎没一门编程语言的第一个程序都叫“你好,世界”,所以先在visual studio 中创建一个Helloworld程序. 各部分的详细内容: Main方法是程序运行的起点,最重要的代码就写在Main ...

  5. Web 播放声音 — Flash 篇 (播放 AMR、WAV)

    本文主要介绍 Flash 播放 AMR 格式 Base64码 音频. 在此之前么有接触过 Flash ,接触 AS3 是一头雾水,不过幸好有 TypeScript 和 JavaScript 的基础看起 ...

  6. uexQQ插件学习心得

    uexQQ插件学习心得 uexQQ插件的作用:通过qq可以分享图文,音乐,应用到相应的qq空间.支持手机客户端分享和手机webQQ分享.下面我们就来看一看他的一些方法. 我们先说一下分享的步骤,这个步 ...

  7. ios safari 标签发送到桌面自定义图标方法

    iphone 修改safari 发送到桌面图标 试了几次,总结如下: 1.全屏方法 <meta name="viewport" content="width=dev ...

  8. 《C++ API设计》作者Martin Reddy访谈问题征集

    Martin Reddy博士是软件行业的一名老兵,有着15年以上的从业经验,共撰写过40多篇论文,拥有3项软件专利,并与他人合著了Level of Detail for 3D Graphics.另外, ...

  9. 初始angular框架(1)

    作为一个从来没有使用过的angular框架的小白  第一步肯定是 看文档!  没错就是看文档了!

  10. 处理handler中的内存泄漏

    package de.bvb.test; import android.app.Activity; import android.os.Bundle; import android.os.Handle ...