IOS XMPP(即时通讯的框架)
#import "AppDelegate.h"
#import "XMPPFramework.h"
/*
* 在AppDelegate实现登录 1. 初始化XMPPStream
2. 连接到服务器[传一个JID]
3. 连接到服务成功后,再发送密码授权
4. 授权成功后,发送"在线" 消息
*/
@interface AppDelegate ()<XMPPStreamDelegate>{
XMPPStream *_xmppStream;
} // 1. 初始化XMPPStream
-(void)setupXMPPStream; // 2.连接到服务器
-(void)connectToHost; // 3.连接到服务成功后,再发送密码授权
-(void)sendPwdToHost; // 4.授权成功后,发送"在线" 消息
-(void)sendOnlineToHost;
@end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 程序一启动就连接到主机
[self connectToHost];
return YES;
} #pragma mark -私有方法
#pragma mark 初始化XMPPStream
-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; // 设置代理
[_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, )];
} #pragma mark 连接到服务器
-(void)connectToHost{
NSLog(@"开始连接到服务器");
if (!_xmppStream) {
[self setupXMPPStream];
} // 设置登录用户JID
//resource 标识用户登录的客户端 iphone android XMPPJID *myJID = [XMPPJID jidWithUser:@"wangwu" domain:@"teacher.local" resource:@"iphone" ];
_xmppStream.myJID = myJID; // 设置服务器域名
_xmppStream.hostName = @"teacher.local";//不仅可以是域名,还可是IP地址 // 设置端口 如果服务器端口是5222,可以省略
_xmppStream.hostPort = ; // 连接
NSError *err = nil;
if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){
NSLog(@"%@",err);
} } #pragma mark 连接到服务成功后,再发送密码授权
-(void)sendPwdToHost{
NSLog(@"再发送密码授权");
NSError *err = nil;
[_xmppStream authenticateWithPassword:@"" error:&err];
if (err) {
NSLog(@"%@",err);
}
} #pragma mark 授权成功后,发送"在线" 消息
-(void)sendOnlineToHost{ NSLog(@"发送 在线 消息");
XMPPPresence *presence = [XMPPPresence presence];
NSLog(@"%@",presence); [_xmppStream sendElement:presence]; }
#pragma mark -XMPPStream的代理
#pragma mark 与主机连接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{
NSLog(@"与主机连接成功"); // 主机连接成功后,发送密码进行授权
[self sendPwdToHost];
}
#pragma mark 与主机断开连接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
// 如果有错误,代表连接失败
NSLog(@"与主机断开连接 %@",error); } #pragma mark 授权成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
NSLog(@"授权成功"); [self sendOnlineToHost];
} #pragma mark 授权失败
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
NSLog(@"授权失败 %@",error);
} #pragma mark -公共方法
-(void)logout{
// 1." 发送 "离线" 消息"
XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"];
[_xmppStream sendElement:offline]; // 2. 与服务器断开连接
[_xmppStream disconnect];
} @end
封装好的XMPP工具(登录,注册,注销)
WCXMPPTool.h
#import <Foundation/Foundation.h>
#import "Singleton.h"
#import "XMPPFramework.h" typedef enum {
XMPPResultTypeLoginSuccess,//登录成功
XMPPResultTypeLoginFailure,//登录失败
XMPPResultTypeNetErr,//网络不给力
XMPPResultTypeRegisterSuccess,//注册成功
XMPPResultTypeRegisterFailure//注册失败
}XMPPResultType; typedef void (^XMPPResultBlock)(XMPPResultType type);// XMPP请求结果的block @interface WCXMPPTool : NSObject singleton_interface(WCXMPPTool); @property (nonatomic, strong)XMPPvCardTempModule *vCard;//电子名片 /**
* 注册标识 YES 注册 / NO 登录
*/
@property (nonatomic, assign,getter=isRegisterOperation) BOOL registerOperation;//注册操作 /**
* 用户注销 */
-(void)xmppUserlogout;
/**
* 用户登录
*/
-(void)xmppUserLogin:(XMPPResultBlock)resultBlock; /**
* 用户注册
*/
-(void)xmppUserRegister:(XMPPResultBlock)resultBlock;
@end
WCXMPPTool.m
#import "WCXMPPTool.h" /*
* 在AppDelegate实现登录 1. 初始化XMPPStream
2. 连接到服务器[传一个JID]
3. 连接到服务成功后,再发送密码授权
4. 授权成功后,发送"在线" 消息
*/
@interface WCXMPPTool ()<XMPPStreamDelegate>{
XMPPStream *_xmppStream;
XMPPResultBlock _resultBlock; XMPPvCardCoreDataStorage *_vCardStorage;//电子名片的数据存储 XMPPvCardAvatarModule *_avatar;//头像模块
} // 1. 初始化XMPPStream
-(void)setupXMPPStream; // 2.连接到服务器
-(void)connectToHost; // 3.连接到服务成功后,再发送密码授权
-(void)sendPwdToHost; // 4.授权成功后,发送"在线" 消息
-(void)sendOnlineToHost;
@end @implementation WCXMPPTool singleton_implementation(WCXMPPTool) #pragma mark -私有方法
#pragma mark 初始化XMPPStream
-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; #warning 每一个模块添加后都要激活
//添加电子名片模块
_vCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
_vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage]; //激活
[_vCard activate:_xmppStream]; //添加头像模块
_avatar = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_vCard];
[_avatar activate:_xmppStream]; // 设置代理
[_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, )];
} #pragma mark 连接到服务器
-(void)connectToHost{
WCLog(@"开始连接到服务器");
if (!_xmppStream) {
[self setupXMPPStream];
} // 设置登录用户JID
//resource 标识用户登录的客户端 iphone android // 从单例获取用户名
NSString *user = nil;
if (self.isRegisterOperation) {
user = [WCUserInfo sharedWCUserInfo].registerUser;
}else{
user = [WCUserInfo sharedWCUserInfo].user;
} XMPPJID *myJID = [XMPPJID jidWithUser:user domain:@"teacher.local" resource:@"iphone" ];
_xmppStream.myJID = myJID; // 设置服务器域名
_xmppStream.hostName = @"127.0.0.1";//不仅可以是域名,还可是IP地址 // 设置端口 如果服务器端口是5222,可以省略
_xmppStream.hostPort = ; // 连接
NSError *err = nil;
if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){
WCLog(@"%@",err);
} } #pragma mark 连接到服务成功后,再发送密码授权
-(void)sendPwdToHost{
WCLog(@"再发送密码授权");
NSError *err = nil; // 从单例里获取密码
NSString *pwd = [WCUserInfo sharedWCUserInfo].pwd; [_xmppStream authenticateWithPassword:pwd error:&err]; if (err) {
WCLog(@"%@",err);
}
} #pragma mark 授权成功后,发送"在线" 消息
-(void)sendOnlineToHost{ WCLog(@"发送 在线 消息");
XMPPPresence *presence = [XMPPPresence presence];
WCLog(@"%@",presence); [_xmppStream sendElement:presence]; }
#pragma mark -XMPPStream的代理
#pragma mark 与主机连接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{
WCLog(@"与主机连接成功"); if (self.isRegisterOperation) {//注册操作,发送注册的密码
NSString *pwd = [WCUserInfo sharedWCUserInfo].registerPwd;
[_xmppStream registerWithPassword:pwd error:nil];
}else{//登录操作
// 主机连接成功后,发送密码进行授权
[self sendPwdToHost];
} }
#pragma mark 与主机断开连接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
// 如果有错误,代表连接失败 // 如果没有错误,表示正常的断开连接(人为断开连接) if(error && _resultBlock){
_resultBlock(XMPPResultTypeNetErr);
}
WCLog(@"与主机断开连接 %@",error); } #pragma mark 授权成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
WCLog(@"授权成功"); [self sendOnlineToHost]; // 回调控制器登录成功
if(_resultBlock){
_resultBlock(XMPPResultTypeLoginSuccess);
} } #pragma mark 授权失败
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
WCLog(@"授权失败 %@",error); // 判断block有无值,再回调给登录控制器
if (_resultBlock) {
_resultBlock(XMPPResultTypeLoginFailure);
}
} #pragma mark 注册成功
-(void)xmppStreamDidRegister:(XMPPStream *)sender{
WCLog(@"注册成功");
if(_resultBlock){
_resultBlock(XMPPResultTypeRegisterSuccess);
} } #pragma mark 注册失败
-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{ WCLog(@"注册失败 %@",error);
if(_resultBlock){
_resultBlock(XMPPResultTypeRegisterFailure);
} } #pragma mark -公共方法
-(void)xmppUserlogout{
// 1." 发送 "离线" 消息"
XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"];
[_xmppStream sendElement:offline]; // 2. 与服务器断开连接
[_xmppStream disconnect]; // 3. 回到登录界面
// UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
//
// self.window.rootViewController = storyboard.instantiateInitialViewController;
[UIStoryboard showInitialVCWithName:@"Login"]; //4.更新用户的登录状态
[WCUserInfo sharedWCUserInfo].loginStatus = NO;
[[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox]; } -(void)xmppUserLogin:(XMPPResultBlock)resultBlock{ // 先把block存起来
_resultBlock = resultBlock; // Domain=XMPPStreamErrorDomain Code=1 "Attempting to connect while already connected or connecting." UserInfo=0x7fd86bf06700 {NSLocalizedDescription=Attempting to connect while already connected or connecting.}
// 如果以前连接过服务,要断开
[_xmppStream disconnect]; // 连接主机 成功后发送登录密码
[self connectToHost];
} -(void)xmppUserRegister:(XMPPResultBlock)resultBlock{
// 先把block存起来
_resultBlock = resultBlock; // 如果以前连接过服务,要断开
[_xmppStream disconnect]; // 连接主机 成功后发送注册密码
[self connectToHost];
} @end
自动登录
AppDelegate.m
#import "AppDelegate.h"
#import "XMPPFramework.h"
#import "WCNavigationController.h"
#import "DDLog.h"
#import "DDTTYLogger.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //从沙盒的路径
NSString *path=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; //打开XMPP的日志
[DDLog addLogger:[DDTTYLogger sharedInstance]]; //设置导航栏背景
// [WCNavigationController setupNavTheme]; //从沙盒里加载用户的数据单例
[[WCUserInfo sharedWCUserInfo] loadUserInfoFromSanbox]; //判断用户的登录状态,YES直接来到主界面
if([WCUserInfo sharedWCUserInfo].loginStatus){
UIStoryboard *storayobard=[UIStoryboard storyboardWithName:@"Main" bundle:nil];
self.window.rootViewController=storayobard.instantiateInitialViewController; //自动登录服务
[[WCXMPPTool sharedWCXMPPTool]xmppUserLogin:nil];
} return YES;
}
@end
登录方法
#import "WCBaseLoginViewController.h"
#import "AppDelegate.h" @implementation WCBaseLoginViewController - (void)login{
// 登录 /*
* 官方的登录实现 * 1.把用户名和密码放在WCUserInfo的单例 * 2.调用 AppDelegate的一个login 连接服务并登录
*/ //隐藏键盘
[self.view endEditing:YES]; // 登录之前给个提示 [MBProgressHUD showMessage:@"正在登录中..." toView:self.view]; [WCXMPPTool sharedWCXMPPTool].registerOperation = NO;
__weak typeof(self) selfVc = self; [[WCXMPPTool sharedWCXMPPTool] xmppUserLogin:^(XMPPResultType type) {
[selfVc handleResultType:type];
}];
} -(void)handleResultType:(XMPPResultType)type{
// 主线程刷新UI
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view
];
switch (type) {
case XMPPResultTypeLoginSuccess:
NSLog(@"登录成功");
[self enterMainPage];
break;
case XMPPResultTypeLoginFailure:
NSLog(@"登录失败");
[MBProgressHUD showError:@"用户名或者密码不正确" toView:self.view];
break;
case XMPPResultTypeNetErr:
[MBProgressHUD showError:@"网络不给力" toView:self.view];
default:
break;
}
}); } -(void)enterMainPage{ // 更改用户的登录状态为YES
[WCUserInfo sharedWCUserInfo].loginStatus = YES; // 把用户登录成功的数据,保存到沙盒
[[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox]; // 隐藏模态窗口
[self dismissViewControllerAnimated:NO completion:nil]; // 登录成功来到主界面
// 此方法是在子线程补调用,所以在主线程刷新UI
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
self.view.window.rootViewController = storyboard.instantiateInitialViewController;
}
IOS XMPP(即时通讯的框架)的更多相关文章
- IOS 即时通讯的框架 配置环境
一.了解XMPP 协议(标准)XMPP 即时通讯协议SGIP 短信网关协议 这手机发短信 移动支付和网页支付 0x23232[0,1] 0x23232 0x23232 0x23232 只有协议,必须会 ...
- XMPP即时通讯资料记录
几天开始研究XMPP即时通讯的技术,来实现移动应用的计时聊天功能.记录下参考的博客地址,还挺详细的. http://blog.csdn.net/fhbystudy/article/details/16 ...
- iOS开发之XMPP即时通讯简单实现
首先搭载服务器和数据库 搭载服务器我用的是openfire,数据库用的是mysql 这里推荐两个链接 配置mysql,用的是mysql workbench http://justsee.iteye.c ...
- xmpp即时通讯的笔记(摘抄)
xmpp的使用: 即时通讯 instant messaging(IM) : -->实时收发信息! 即时通讯相关软件: **QQ,MSN,GoogleTalk,AIM,Jabber(XMPP别名 ...
- iOS之即时通讯相关理解
Socket: 1>Socket又称"套接字" 2>网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 3>应用程序通常通 ...
- iOS - IM 即时通讯
1.即时通讯技术 即时通讯(IM:Instant Messaging):又称实时通讯,支持用户在线实时交谈,允许两人或多人使用网络实时的传递文字消息.文件.语音与视频交流. 即时通讯在开发中使用的场景 ...
- iOS:XMPP即时聊天知识
XMPP即时聊天框架:XMPPFramework XMPP The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). 基于XML XM ...
- XMPP即时通讯
XMPP:XMPP是基于XML的点对点通讯协议,The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). XMPP可用于服务类实时通讯,表 ...
- iOS开发--即时通讯常用第三方库
前言 自毕业到现在,从事iOS即时通讯开发已经1年半之久.主要负责Allure开发,目前已上架,可以在苹果商店搜素Allure.Allure模仿微信的交互和设计效果,已经实现微信的大部分功能. 在这里 ...
- XMPP即时通讯基础知识
XMPP参考 一.定义 XMPP 是一种很类似于http协议的一种数据传输协议,它的过程就如同“解包装--〉包装”的过程,用户只需要明白它接受的类型,并理解它返回的类型,就可以很好的利用xmpp来进行 ...
随机推荐
- [PY3]——内置数据结构(7)——字典及其常用操作
字典及其常用操作Xmind图 关于字典 字典是一种key-value结构 字典是无序的 字典的定义 # {}大括号可以直接定义一个空字典 In [1]: d={};type(d) Out[1]: di ...
- angular2自学笔记(二)---路由、服务等八大主要构造块
angular的思想:总是把数据访问工作委托给一个支持性服务类. Angular 应用的:用 Angular 扩展语法编写 HTML 模板, 用组件类管理这些模板,用服务添加应用逻辑, 用模块打包发布 ...
- 有关css和js针对不同浏览器兼容的问题
首先谈一下浏览器,虽然现在ie依然是浏览器市场的老大,大约占有67%的份额,但是由于其各方面的欠缺,用户开始选择其他浏览器作为自己浏览网页的主要 工具,比如firefox.theworld.maxth ...
- vs2015编译时CS1056 C# Unexpected character解决办法
https://stackoverflow.com/questions/42932577/error-cs1056-unexpected-character-running-the-msbuild-o ...
- java 通用对象排序
一个排序类,一个排序util? no.no.no…… 使用反射机制,写了一个通用的对象排序util,欢迎指正. 实体类: package entity; public class BaseTypeEn ...
- Java 集合:List(ArrayList,LinkedList)
- SQL修改表结构
--(1)向数据库Student表中添加Name字段 use MR_NXT alter table student add Name char(20) --(2)将Student表中Name的字段的数 ...
- BZOJ3600:没有人的算术
传送门 如果能给每个 \(pair\) 按照权值编号就好了 假设之前已经有了所有的权值的编号,现在考虑编号新的 \(pair\) 如果看过了陈立杰的论文的话,不难得到一个重量平衡树的做法 给树上每个子 ...
- css控制一个元素点击后, 改变另外一个元素的状态
1.点击后改变子元素.myclass:active span{ color:#00f;} 此方式在ios下不生效,chrome下正常 2.改变下一个兄弟元素.myclass:active +span ...
- Java 中你必须了解的常用类(8)
Java 中的包装类 相信各位小伙伴们对基本数据类型都非常熟悉,例如 int.float.double.boolean.char 等.基本数据类型是不具备对象的特性的, 比如基本类型不能调用方法.功能 ...