1.创建一个新工程

2.导入XMPP框架

最新的XMPP框架下载地址:https://github.com/robbiehanson/XMPPFramework

将XMPP的几个文件夹拖进工程中,需要的文件如下:

然后把Sample_XMPPFramework.h改名为XMPPFramework.h

接下来导入两个依赖库:libresolv.dylib和libxml2.dylib,然后添加header search:

再添加一个pch文件

在pch文件中添加如下代码:

#ifdef __OBJC__
#import <UIKit/UIKit.h> #import "XMPPFramework.h"
#endif

再然后设置工程的pch文件

$SRCROOT后面是项目名/pch文件名。

做完以上步骤,项目就可以编译成功啦!

现在开始搭建项目的登录界面:

首先封装一个XMPP工具类:JKXMPPTool

.h文件

#import <Foundation/Foundation.h>

@interface JKXMPPTool : NSObject<XMPPStreamDelegate>

@property (nonatomic, strong) XMPPStream *xmppStream;
// 模块
@property (nonatomic, strong) XMPPAutoPing *xmppAutoPing;
@property (nonatomic, strong) XMPPReconnect *xmppReconnect; @property (nonatomic, assign) BOOL xmppNeedRegister;
@property (nonatomic, copy) NSString *myPassword; + (instancetype)sharedInstance;
- (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password;
- (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password; @end

.m文件

#import "JKXMPPTool.h"

@implementation JKXMPPTool

static JKXMPPTool *_instance;
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [JKXMPPTool new];
}); return _instance;
} - (XMPPStream *)xmppStream
{
if (!_xmppStream) {
_xmppStream = [[XMPPStream alloc] init]; //socket 连接的时候 要知道host port 然后connect
[self.xmppStream setHostName:kXMPP_HOST];
[self.xmppStream setHostPort:kXMPP_PORT];
//为什么是addDelegate? 因为xmppFramework 大量使用了多播代理multicast-delegate ,代理一般是1对1的,但是这个多播代理是一对多得,而且可以在任意时候添加或者删除
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; }
return _xmppStream;
} - (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password
{
// 1.建立TCP连接
// 2.把我自己的jid与这个TCP连接绑定起来(即使匿名登录,依然得设置JID,只是我们可以设置一个任意的JID,例如<span style="font-family: Arial, Helvetica, sans-serif;">anonymous@<domain></span>)
// 3.认证(登录:验证jid与密码是否正确,加密方式 不可能以明文发送)--(出席:怎样告诉服务器我上线,以及我得上线状态
//这句话会在xmppStream以后发送XML的时候加上 <message from="JID">
[self.xmppStream setMyJID:JID];
self.myPassword = password;
self.xmppNeedRegister = NO;
[self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil];
} //注册方法里没有调用auth方法
- (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password
{
[self.xmppStream setMyJID:JID];
self.myPassword = password;
self.xmppNeedRegister = YES;
[self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil];
} - (void)goOnline
{
// 发送一个<presence/> 默认值avaliable 在线 是指服务器收到空的presence 会认为是这个
XMPPPresence *presence = [XMPPPresence presence]; //发送复杂一点的出席状态
//<presence type="avaliable">
// <status>我很忙</status>
// <show>xa</show>
// </presence>
[presence addChild:[DDXMLNode elementWithName:@"status" stringValue:@"我现在很忙"]];
[presence addChild:[DDXMLNode elementWithName:@"show" stringValue:@"xa"]]; [self.xmppStream sendElement:presence];
} #pragma mark ===== XMPPStream delegate =======
//socket 连接建立成功
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
{
NSLog(@"%s",__func__);
} //这个是xml流初始化成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
NSLog(@"%s",__func__);
//匿名登录 会随机生成一个username和JID,这个是在服务器的内存中随机生成,不会写入服务器的数据表,例如生成的jid为<p class="p1"><span class="s1">1nv8l4khxg@im.joker.cn/1nv8l4khxg</span></p>
//为了防止客户端匿名登录,服务器有策略关闭匿名
// [self.xmppStream authenticateAnonymously:nil];
if (self.xmppNeedRegister) {
[self.xmppStream registerWithPassword:self.myPassword error:nil];
} else {
[self.xmppStream authenticateWithPassword:self.myPassword error:nil];
}
} - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
NSLog(@"%s",__func__);
} //登录失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
NSLog(@"%s",__func__);
} //登录成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
NSLog(@"%s",__func__); [self goOnline]; [[NSNotificationCenter defaultCenter] postNotificationName:kLOGIN_SUCCESS object:nil];
} @end

然后是登录功能:

登录按钮的action如下:

#pragma mark - click event
/** 登录事件 */
- (IBAction)loginClick:(id)sender {
NSString *username = _usernameField.text;
NSString *password = _passwordField.text; NSString *message = nil;
if (username.length <= 0) {
message = @"用户名未填写";
} else if (password.length <= 0) {
message = @"密码未填写";
} if (message.length > 0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
[alertView show];
} else {
[[JKXMPPTool sharedInstance] loginWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password];
}
}

用通知返回登录成功的消息

- (void)loginSuccess
{
NSLog(@"loginSuccess"); [self performSegueWithIdentifier:@"loginSegue" sender:self];
}

再然后实现注册的功能:

- (IBAction)registAction:(id)sender {
NSString *username = _usernameField.text;
NSString *password = _passwordField.text;
NSString *confirm = _confirmField.text; NSString *message = nil;
if (username.length <= 0) {
message = @"用户名未填写";
} else if (password.length <= 0) {
message = @"密码未填写";
} else if (confirm.length <= 0) {
message = @"确认密码未填写";
} if (message.length > 0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
[alertView show];
} else if (![password isEqualToString:confirm]) {
message = @"密码与确认密码不一致";
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil];
[alertView show];
} else {
[[JKXMPPTool sharedInstance] registerWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password];
}
}

因为注册时,不需要进行认证,注册会直接返回BOOL结果,所以改进连接代理方法:

//这个是xml流初始化成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
NSLog(@"%s",__func__);
if (self.xmppNeedRegister) {
BOOL result = [self.xmppStream registerWithPassword:self.myPassword error:nil];
NSNumber *number = [NSNumber numberWithBool:result]; [[NSNotificationCenter defaultCenter] postNotificationName:kREGIST_RESULT object:number]; } else {
[self.xmppStream authenticateWithPassword:self.myPassword error:nil];
}
}

下载地址:点击下载

github地址:https://github.com/Joker-King/ChatDemo

XMPP系列(二)----用户注册和用户登录功能的更多相关文章

  1. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  2. Struts2整合Hibernate3实现用户登录功能

    所用技术:struts2 ,hibernate,jsp,mysql 本DEMO仅仅实现用户登录功能,采用MVC思想,自己也觉得相对是比较简单,比较容易理解数据流向的一个例子,通过整合这个过程,能够清晰 ...

  3. JavaWeb学习记录(六)——用户登录功能

    使用JDBC.spring框架.servlet实现一个简单的用户登录功能. 一.mySql数据库 SET FOREIGN_KEY_CHECKS=0; -- ---------------------- ...

  4. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  5. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(四)——对 run.py 的调整

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  6. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  7. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(三)——使用Flask-Login库实现登录功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  8. .net reactor 学习系列(二)---.net reactor界面各功能说明

    原文:.net reactor 学习系列(二)---.net reactor界面各功能说明         安装了.net reactor之后,可以在安装目录下找到帮助文档REACTOR_HELP.c ...

  9. 实现Web上的用户登录功能

    关于如何实现web上的自动登录功能 文章来源http://coolshell.cn/articles/5353.html Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能 ...

随机推荐

  1. 凸函数与Jensen不等式

    这个是在凸优化里面看的,在EM算法中看有用到,所以用latex写了篇回忆用的小短文,现在不会把latex产生的pdf怎么转变成放到这里的内容. 所以我选择直接贴图. 这个pdf可以在我的资源里找到.  ...

  2. 将String转换为其表示的路径画到屏幕上

    关于这个问题,我已经在另一篇blog中有所提及: CoreText精彩文字轮廓绘制动画的一点改进 不过原有的转换代码使用Obj-C写的,在这里我们尝试将其转换为Swift语言,然后利用它实现一个测试小 ...

  3. JSP1.x 自定义标签

    Tag接口 任何一个标签都对应着一个java类,该类必须实现Tag接口,JSP遇到一个标签后后,将通过一个tld文件查找该标签的实现类,并运行该类的相关方法 import javax.servlet. ...

  4. Android Studio安装Genymotion插件

    Android Studio安装Genymotion插件 Eclipse就不介绍了,谷歌都已经放弃Eclipse了,你还在坚持什么. 安装Genymotion 官网:https://www.genym ...

  5. iOS开发之字数不一的多标签Demo

    有朋友让帮他写一个封装的字数不一的多标签视图,所以今天将代码展示一下,供大家学习 代码中封装了两种方法,分别是:1.传递数组,数组中是NSString类型的方法:2.传递数组,数组中是NSDictio ...

  6. 18 UI美化自定义主题样式代码

    自定义主题 假设我们我们对现有的样式不大满意 那么可在工程目录res/values下的styles.xml自定义 方法: 1. res/values下的styles.xml文件中自定义一个标签 < ...

  7. scala学习笔记1(表达式)

    <pre name="code" class="plain">//Scala中的 main 函数需要存在于 object 对象中,我们需要一个obj ...

  8. install_driver(Oracle) failed: Can't load `.../DBD/Oracle/Oracle.so' for module DBD::Oracle

    Description This section is from the "Practical mod_perl " book, by Stas Bekman and Eric C ...

  9. Android进阶(三)android httpClient 支持HTTPS的访问方式

    项目中Android https请求地址遇到了这个异常(无终端认证): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 是S ...

  10. iOS中 DataBase SQL数据库 UI_高级

    SQL(Structured query Lauguage) :结构化 查询 语言 1.创建表格的SQL语句 create table if not exists Teacher(tea_id int ...