7. Swift 基于Xmpp和openfire实现一个简单的登录注册
1. 基本步骤:首先导入Xmpp框架,配置环境
-》由于我们使用的是OC的Xmpp框架,再进行Swift开发时需要进行桥接。 具体方法就是创建一个基于c的.h的头文件,然后将我们需要编译OC的语言的头文件包含这个.h文件中;
-》然后导入如下库文件,在头头文件选择路径中
如上图, 设置header Search paths 设置头文件的搜索路径,导入libxml2库文件相对路径,***注意前面是 usr 。以前第一次装的时候写成user找了半个多小时
-> 然后创建界面,随便弄两个框框和按钮自定义一个建议的界面。
应为在应用程序中用户名和密码可能被反复的使用,所以我们需要讲它门设置成一个单利类。
如下代码所示:
import UIKitclass 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 = 0static var instance : WSBUserinfo? = nil}dispatch_once(&Singleton.dispatchOne) { () -> Void inSingleton.instance = WSBUserinfo()}return Singleton.instance!}}
//由于登录流程设计到了xmpp流协议实现,步骤较多。这里我们可以单独封装一个工具类。这样我们的登录和注册的主控制器就能得到极大的解脱:
在登录控制器中我们只需要将输入框的用户输入信息赋值到单利用户信息类 UserInfo里
然后调用 单利工具类的 usrLogin()方法及可自动完成所有的登录流程
再通过指定一个协议,实现对登录和注册状态的监听;
注册控制器的逻辑同上,这里就不重复了 。
注意点1:再每次连接请求时先把之前的连接断开,这样能避免一个账号长连接而其它的账号无法连接。
注意点2:再发送登录注册时中间都涉及到了共同的连接请求和连接状态请求,我们需要在单利类中建立一个Bool属性值做分支判定,这样我们只需要在方法内部做简单的调整,从而省去大量的代码步骤。
具体步骤请看下面代码
import UIKitclass WSBLoginViewController: UIViewController,WSBXMPPLoginDelegate {@IBOutlet weak var userNameField: UITextField!@IBOutlet weak var userPasswdField: UITextField!@IBAction func loginBtnClick(sender: AnyObject) {WSBUserinfo.getShareInstance().isLogin = trueprint("用户名:\(userNameField.text!)")dprint("密码是:\(userPasswdField.text!)")// 把用户名 密码存入工具类 WSBUserinfo 这个单例对象中WSBUserinfo.getShareInstance().userName = userNameField.text!WSBUserinfo.getShareInstance().userPasswd = userPasswdField.text!// 调用XMPP 工具类 完成登录// 登录之前先给WSBXMPPTool设置代理WSBXMPPTool.getSharedInstance().loginDelegate = selfWSBXMPPTool.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 UIKitclass WSBRegisterViewController: UIViewController,WSBXMPPRegisterDelegate {@IBOutlet weak var userRegiserName: UITextField!@IBOutlet weak var userRegisterPasswd: UITextField!@IBAction func registerBtnClick(sender: AnyObject) {// 说明这是注册行为WSBUserinfo.getShareInstance().isLogin = falseWSBUserinfo.getShareInstance().userRegisterName = self.userRegiserName.text!WSBUserinfo.getShareInstance().userRegisterPasswd = self.userRegisterPasswd.text!// 调用XMPPTool的 注册方法WSBXMPPTool.getSharedInstance().registerDelegate = selfWSBXMPPTool.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!// 登录的Delegateweak var loginDelegate : WSBXMPPLoginDelegate?// 注册的Deletegateweak var registerDelegate : WSBXMPPRegisterDelegate?// 保证xmppStream 使用时非空override init() {super.init()setupXmppStream()}class func getSharedInstance() -> WSBXMPPTool {struct Singleton {static var predicate : dispatch_once_t = 0static var instance : WSBXMPPTool? = nil}dispatch_once(&Singleton.predicate) { () -> Void inSingleton.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? = nilif 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 = XMPPHOSTNAMExmppStream.hostPort = XMPPPORTdo {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是 nilif 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 = functionself.connectToHost()}
3.4在XmppTool工具类中需要使用回调的地方执行次闭包函数,下面以其中一个为例, 网络连接错误,注册成功,失败,这三处都需要调用。
registerCloser!(result: XMPPResultType.XMPPResultTypeRegisterSuccess)
3.5 我们在主控制器中只需要拿出闭包函数的result的状态及可判断是否 后台执行的结果.注意需要使用weakself,否则无法释放。
weak var weakVc = selfWSBXMPPTool.getSharedInstance().userRegister { (result) -> Void inswitch result{case .XMPPResultTypeRegisterSuccess:print("注册成功")weakVc?.dismissViewControllerAnimated(true, completion: nil)case .XMPPResultTypeRegisterFailed:print("注册失败")case .XMPPResultTypeRegisterNetError:print("网络错误")} } }
转载于:https://www.cnblogs.com/wwoo/p/5225592.html
7. Swift 基于Xmpp和openfire实现一个简单的登录注册相关推荐
- 基于android校园订餐APP,简单实现登录注册功能(SharedPreferences)
基于android校园订餐APP,简单实现登录注册功能(SharedPreferences) 欢迎浏览本篇文章 界面效果图 页面设计代码 源代码 欢迎浏览本篇文章 大家好! 这是小编首次在博客上写的文 ...
- 一个简单的登录注册网页的实现
一个简单的登录注册网页的实现 通过 标签让标签内的内容居中显示,再通过标签中的method属性来设置请求方式为post(一般涉及密码等机密数据都用post请求):再通过action来设置请求地址.这其 ...
- 小白教程——Windows下用PHP写一个简单的登录注册页面(二)
哈喽,看到这里希望小伙伴们都把wampserver环境安装好了,如果还没有安装或创建数据表就移步去看我上一篇文章吧.OK~接下我们将进入代码实现部分,首先我们需要一个文本编辑器,可以是电脑自带的not ...
- 一个简单的登录注册界面流程介绍
登录页面实现 其他页面的实现可以到github上克隆下来 login_interface login_server 一.用户登录 1.密码登录 流程: 用户输入密码: 表单使用正则验证用户名和密码格式 ...
- HTML写一个简单的登录注册界面
页面样式 HTML代码 <html lang="en"> <head><meta charset="UTF-8"><t ...
- python做一个登录注册界面_Python 实现简单的登录注册界面
Python 实现简单的登录注册界面 注意:编写代码之前需要导入很重要的包 import tkinter as tk import pickle from tkinter import message ...
- Android基于XMPP Smack openfire 开发的聊天室
公司刚好让做即时通讯模块,服务器使用openfire,偶然看到有位仁兄的帖子,拷贝过来细细研究,感谢此仁兄的无私,期待此仁兄的下次更新 转自http://blog.csdn.net/lnb333666 ...
- (超多图)基于Android studio开发的一个简单入门小应用(超级详细!!)(建议收藏)
基于Android studio开发的一个简单入门小应用 一.前言 二.前期准备 三.开发一个小应用 五.运行应用 一.前言 在暑假期间,我学习JAVA基础,为了能早日实现自己用代码写出一个app的& ...
- 基于Servlet+JSP+JavaBean开发模式的用户登录注册
基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+JavaBean模式(MVC)适合开发复 ...
- 【转载】 javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册 - 孤傲苍狼 - 博 http://www.cnblogs.com/xdp-gacl/
javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+Ja ...
最新文章
- 详细的聊聊接口性能优化的11个小技巧 不收藏对不起我
- 远程连接——Win连接远程Linux的软件
- Unable to lock JVM Memory: error=12--elasticsearch
- lass翻译_【专题讲座】政务翻译人才培训系列讲座(1)
- windows如何使用ssh登录ubuntu
- 一张图学会数据库迁云最佳路径
- python工程师工资状况_【python工程师工资|python工程师待遇怎么样】-看准网
- java程序设计_Java程序设计--接口interface(笔记)
- Soul 网关源码阅读(二)代码初步运行
- android 定时请求(两种实现方式)
- vivoy67Android7升级包,vivoy67刷机包
- 学术会议论文查重吗_会议论文会不会进行摘要查重?
- python十六进制转pcap文件_python处理pcap文件——数据提取
- 暴风电视TV 55X 3.0系统通过adb Root修改桌面,删除无用app
- Mac使用技巧:M1芯片的电脑恢复模式如何开启
- 单视图几何Vanish Point(消失点/灭点)计算方法——Robert_T_Collins(罗伯特·柯林斯)算法
- 常见的hash函数算法
- 一键制作所有微信好友头像墙照
- [微信小程序] 单张、多张图片上传(图片转base64格式)实践经验
- 史上最全的边缘计算应用场景