iOS中XMPP即时通讯实现的主要步骤

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

这里只是列出实现的只要步骤,不是全部代码。

首先导入XMPPFramework,及相关配置,完成后开始。

创建一个XMPPHelper 类来管理要进行的操作。

XMPPHelper.h文件如下

1typedefvoid(^loginSuccessBlock)(void);2typedefvoid(^loginFailBlock)(NSString *info);3typedefvoid(^fenchFridendList)(idresult);4typedefvoid(^logoutSuccessBlock)(void);5typedefvoid(^registerSuccessBlock)(void);6typedefenum{7kTypeLogin,8kTypeRegister9}ConnectType;10#import<Foundation/Foundation.h>11#definekXMPPHosetName @"lala"12#definekXMPPHostAddress @"192.168.13.17"13#definekHostPort 52221415@interfaceXMPPHelper : NSObject16{1718ConnectType _connectType;1920}21@PRoperty(nonatomic,strong)XMPPStream *stream;22@property(nonatomic,strong)XMPPRoster *roster;23@property(nonatomic,copy)NSString *username;24@property(nonatomic,copy)NSString *passWord;2526@property(nonatomic,copy)loginSuccessBlock loginSuccessBlock;27@property(nonatomic,copy)loginFailBlock loginFailBlock;28@property(nonatomic,copy)fenchFridendList fenchFriendList;29@property(nonatomic,copy)logoutSuccessBlock logoutSuccessBlock;30@property(nonatomic,copy)registerSuccessBlock registerSuccessblock;3132+(instancetype)shareInstance;33//登陆34-(void)login:(NSString *)username password:(NSString *)password loginSuccessBlock:(loginSuccessBlock)block loginFailBlock:(loginFailBlock)failBlcok;35//获取好友列表36-(void)loadFriendList:(fenchFridendList)fenchfriendList;37//发送消息38-(void)sendMessage:(NSString *)message toUser:(NSString *)jid;39//注销40-(void)logoutAction:(logoutSuccessBlock)block;41//注册42-(void)registerAction:(NSString *)username password:(NSString *)password registerSuccessBlock:(registerSuccessBlock)registerBlock;4344@end

XMPPHelper.m文件如下

#definekHostAddress @"192.168.13.12"#definekHostName @"zy"#defineKHostPort 5222#import"XMPPHelper.h"#import"User.h"staticXMPPHelper *helper =nil;@interfaceXMPPHelper() <XMPPStreamDelegate>{

ConnectTyep _connectType;

}@end@implementationXMPPHelper//单例+(instancetype) shareInstance {staticdispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

helper=[[XMPPHelper alloc] init];

[helper _stepXMPPHelper];

});returnhelper;

}//初始化的操作- (void) _stepXMPPHelper {//初始化流对象.self.stream =[[XMPPStream alloc] init];//创建自动连接的对象,当意外断开的时候,可以进行自动连接.XMPPReconnect *reConnect =[[XMPPReconnect alloc] init];//初始化花名册对象(好友列表)//存储方式.XMPPRosterCoreDataStorage *storage =[[XMPPRosterCoreDataStorage alloc] init];

self.roster=[[XMPPRoster alloc] initWithRosterStorage:storage];//建立对象之间的联系//激活.[reConnect activate:self.stream];//激活,使用花名册对象.[self.roster activate:self.stream];//设置代理;[self.stream addDelegate:self delegateQueue:dispatch_get_main_queue()];

[self.roster addDelegate:self delegateQueue:dispatch_get_main_queue()];//设置服务器的基本信息.//服务器的地址[self.stream setHostName:kHostAddress];

[self.stream setHostPort:KHostPort];//端口号}#pragmamark XMPP 对外公开方法

- (void) login:(NSString *)userName password:(NSString *)password loginSuccessBlock:(LoginSuccessBlock)block loginFailBlock:(LoginFailBlock)failBlock {

_connectType=kTypeLogin;

self.userName=userName;

self.password=password;

self.loginFailBlock=failBlock;

self.loginSuccessBlock=block;//登录的流程.if(![self connect]) {//连接失败的时候 调用失败的blockif(self.loginFailBlock) {

self.loginFailBlock(@"网络错误");

}

}

}//发起连接-(BOOL) connect {//设置用户的jidNSString *jidString = [NSString stringWithFormat:@"%@@%@",self.userName,kHostName];//创建了一个jid对象XMPPJID *jid =[XMPPJID jidWithString:jidString];

[self.stream setMyJID:jid];

NSError*ERROR =nil;return[self.stream connectWithTimeout:10error:&ERROR];

}//上线的方法- (void) online {//默认情况下 上线的状态XMPPPresence *presence =[XMPPPresence presence];

[self.stream sendElement:presence];

}//下线的方法- (void) outLine {

XMPPPresence*presence = [XMPPPresence presenceWithType:@"unavailable"];//unavailable 离线的意思//发送离线状态[self.stream sendElement:presence];

}//查询好友列表/**

<iq from='guojing@wxhl' type='get' id='roster_1' to='域名'>

<queryxmlns='jabber:iq:roster'/> <!-- iq 信息有多种,根据命名空间来区分-->

</iq>*/- (void) loadFriendList :(FentchFriendList) fentchFriendList {

self.fentchFriendList=fentchFriendList;//创建xml片段//创建<iq></iq>NSXMLElement *iqElement = [NSXMLElement elementWithName:@"iq"];

XMPPJID*jid =self.stream.myJID;

[iqElement addAttributeWithName:@"from"stringValue:[jid description]];//jid.domain ---> 服务器的域名[iqElement addAttributeWithName:@"to"stringValue:jid.domain];

[iqElement addAttributeWithName:@"type"stringValue:@"get"];

[iqElement addAttributeWithName:@"id"stringValue:@"123456"];//创建子节点NSXMLElement *queryElement = [NSXMLElement elementWithName:@"query"xmlns:@"jabber:iq:roster"];//给iq节点增加子节点.[iqElement addChild:queryElement];//发送请求(好友列表)[self.stream sendElement:iqElement];

}//发送消息//发送消息的格式/**

<message

to='huangrong@wxhl'

from='guojing@wxhl'

type='chat'

xml:lang='en'>

<body>有个bug帮我看下</body>

</message>*/- (void) sendMessage:(NSString *)message toUser:(NSString *) jid {//NILif(!message || [message isEqualToString:@""]) {return;

}

NSXMLElement*messageElement = [NSXMLElement elementWithName:@"message"];

[messageElement addAttributeWithName:@"to"stringValue:jid];

XMPPJID*myJid =self.stream.myJID;

[messageElement addAttributeWithName:@"from"stringValue:myJid.description];

[messageElement addAttributeWithName:@"type"stringValue:@"chat"];

[messageElement addAttributeWithName:@"xml:lang"stringValue:@"en"];//<message></message>创建完毕//创建子节点<body></body>NSXMLElement *bodyElement = [NSXMLElement elementWithName:@"body"stringValue:message];

[messageElement addChild:bodyElement];//发送消息[self.stream sendElement:messageElement];

}//注销方法- (void) logOutAction : (LogoutSuccessBlock) block {//发送离线的消息[self outLine];//断开连接,主动断开链接[self.stream disconnect];if(block) {

block();

}

}//注册的方法- (void) registerUser:(NSString *)userName password:(NSString *)password registerSuccessBlock:(RegisterSuccessBlock) block {

_connectType=kTypeRegister;//连接self.userName =userName;

self.password=password;

self.registerBlock=block;

[self connect];

}#pragmamark - XMPP DELEGAET

- (void)xmppStreamDidConnect:(XMPPStream *)sender {

NSLog(@"连接成功");//注册流程和登录流程都要使用该方法.在这里就要进行逻辑上判断if(_connectType ==kTypeRegister) {

[self.stream registerWithPassword:self.password error:nil];

}elseif(_connectType ==kTypeLogin){//如果连接成功,则继续验证密码.[self.stream authenticateWithPassword:self.password error:nil];

}

}//验证成功的方法- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {

NSLog(@"验证成功");//要调用成功的block//发送上线的状态.[self online];if(self.loginSuccessBlock) {

self.loginSuccessBlock();

}

}//验证失败的方法- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error {

NSLog(@"验证失败");//如果认证失败的话,要主动断开连接[self.stream disconnect];if(self.loginFailBlock) {

self.loginFailBlock(@"密码错误");

}

}//获取查询信息- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {/**

//根节点

<iq xmlns="jabber:client" type="result" id="123456" to="1234@zy/f54fcd02">

<query xmlns="jabber:iq:roster">

<item jid="gxb@localhost" name="" ask="subscribe" subscription="none">

<group>联系人列表</group>

</item>

<item jid="laoyan@zy" name="laoyan" subscription="both">

<group>12</group>

</item>

<item jid="deskmate@zy" name="deskmate" subscription="both">

<group>12</group>

<group>12</group>

</item>

<item jid="test123@zy" name="test123" subscription="both">

<group>联系人列表</group>

</item>

<item jid="zhengqingqing@192.168.13.12" name="" ask="subscribe" subscription="none">

<group>联系人列表</group>

</item>

<item jid="liuweiwei@zy" name="" subscription="both">

<group>让你变绿</group>

<group>让你变绿</group>

</item>

<item jid="zhengqingqing@zy" name="zhengqingqing" subscription="both">

<group>让你变绿</group>

</item>

<item jid="gxb1@zy" name="" subscription="both">

<group>联系人列表</group>

<group>联系人列表</group>

<group>变绿了</group>

</item>

<item jid="123456@localhost" name="" ask="subscribe" subscription="none">

<group>联系人列表</group>

</item>

</query>

</iq>*///需要要类型是 字典/**

dic = {

"联系人列表":[user1,user3],

"12":[user2]

}*/NSMutableDictionary*results =[NSMutableDictionary dictionary];

NSXMLElement*queryElement =iq.childElement;//遍历Query节点User *user =nil;for(NSXMLElement *itemElementinqueryElement.children) {

user=[[User alloc] init];

NSString*jidString = [itemElement attributeStringValueForName:@"jid"];

user.jid=jidString;

NSString*userName = [itemElement attributeStringValueForName:@"name"];

user.username=userName;for(NSXMLElement *groupElementinitemElement.children) {//组名 12NSString *groupString =groupElement.stringValue;

NSMutableArray*users =results[groupString];if(users ==nil) {

users=[NSMutableArray array];

results[groupString]=users;

}

[users addObject:user];

}

}if(self.fentchFriendList) {

self.fentchFriendList(results);

}

NSLog(@"获取好友列表 %@",results);returnYES;

}//监听外部传过来的数据,就是如果有好友发来信息,则,回调此方法./**

//传过来很多message标签,我们只需要带body的message标签

<message xmlns="jabber:client" type="chat" id="purplea775e98a" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><composing xmlns="http://jabber.org/protocol/chatstates"/></message>

2015-11-18 09:35:20.264 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98b" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/><body>sad</body></message>

2015-11-18 09:35:30.491 WeChat[3162:161262] message is <message xmlns="jabber:client" type="chat" id="purplea775e98c" to="1234@zy" from="gxb1@zy/MacdeMacBook-Pro-3"><active xmlns="http://jabber.org/protocol/chatstates"/></message>*/- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {//判断当前的message标签是否带body子标签if([message isChatMessageWithBody]) {

NSString*body =message.body;//获取发信息的人的jidXMPPJID *jidFrom =message.from;

NSDictionary*messageDic =@{@"fromUser":jidFrom.description,@"text":body

};//通知,发出接收消息的通知[[NSNotificationCenter defaultCenter] postNotificationName:kRecevieMessageNotificationobject:nil userInfo:messageDic];

}

}//注册成功调用的方法- (void)xmppStreamDidRegister:(XMPPStream *)sender {

_connectType=kTypeLogin;

self.loginSuccessBlock=self.registerBlock;

self.registerBlock=nil;

[self xmppStreamDidConnect:sender];

}@end

把宏定义改成自己的参数,在相关的UI操作代码中创建 单例XMPPHelper 然后调用相关方法,并在相关的代理方法中实现必要的操作就可以了。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航