XMPPManager.h
#import
#import "XMPPFramework.h"
//宏定义通知名
#define kRecieveMessageNotification @"RecieveMessageNotification"
//定义登陆成功失败block
typedef void(^LoginSuccessBlock)(void);
typedef void(^LoginFailBlock)(NSString *);
//定义注册成功失败block
typedef void(^RegisterSuccessBlock)(void);
typedef void(^RegisterFailBlock)(NSString *);
typedef void(^FriendsListBlock)(id result);
//宏定义主机名 IP 端口号
#define KHostName @"ljp"
#define KHostIP @"192.168.0.140"
#define KHostPort 5222
@interface XMPPManager : NSObject
+ (instancetype)shareManager;
//登录
- (void)loginWithUsername:(NSString *)username password:(NSString *)password successBlock:(LoginSuccessBlock)successBlock failBlock:(LoginFailBlock)failBlock;
//注册
- (void)registerWithUsername:(NSString *)username password:(NSString *)password successBlock:(RegisterSuccessBlock)successBlock failBlock:(RegisterFailBlock)failBlock;
//下线
- (void)goOffline;
//设置好友列表
- (void)setFriendsListBlock:(FriendsListBlock)block;
//发送消息
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid;
@end
XMPPManager.m
#import "XMPPManager.h"
#import "XMPPFramework.h"
#import "User.h"
//枚举连接类型
typedef enum{
XMPPConnectLogin,
XMPPConnectRegister
}XMPPConnectType;
@interface XMPPManager ()<XMPPStreamDelegate, XMPPRosterDelegate>
{
XMPPStream *_xmppStrem;
XMPPRoster *_xmppRoster;
NSString *_username;
NSString *_password;
LoginSuccessBlock _loginSusseccBlock;
LoginFailBlock _loginFailBlock;
RegisterSuccessBlock _registerSuccessBlock;
RegisterFailBlock _registerFailBlock;
FriendsListBlock _friendsListBlock;
XMPPConnectType _xmppConnectType;
}
@end
@implementation XMPPManager
//自定义XMMP管理对象
+ (instancetype)shareManager {
static XMPPManager *manager = nil;
if (manager == nil) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[super allocWithZone:nil] init];
[manager setupXMPPManager];
});
}
return manager;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self shareManager];
}
- (instancetype)copy {
return self;
}
//自定义XMMP管理对象
- (void)setupXMPPManager {
//1 创建数据流对象
_xmppStrem = [[XMPPStream alloc] init];
//2 设置重链接对象
XMPPReconnect *reconnect = [[XMPPReconnect alloc] init];
//绑定重链接对象到strem
[reconnect activate:_xmppStrem];
//3 创建花名册对象(好友列表)
//XMPPRosterCoreDataStorage 花名册存储对象
XMPPRosterCoreDataStorage *rcds = [[XMPPRosterCoreDataStorage alloc] init];
_xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:rcds];
//绑定花名册对象到strem
[_xmppRoster activate:_xmppStrem];
//4 设置主机名和端口号
[_xmppStrem setHostName:KHostName];
[_xmppStrem setHostPort:KHostPort];
//5 设置代理对象
[_xmppStrem addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
#pragma mark - 连接
- (BOOL)connect {
//拼接JID
NSString *jidString = [NSString stringWithFormat:@"%@@%@", _username, KHostName];
//设置JID
XMPPJID *jid = [XMPPJID jidWithString:jidString];
//开连接
_xmppStrem.myJID = jid;
//开始连接服务器,返回连接状态
XMPPStreamTimeoutNone永不超时
return [_xmppStrem connectWithTimeout:XMPPStreamTimeoutNone error:nil];
}
//连接成功以后调用
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
//判断连接类型是登陆还是注册
if (_xmppConnectType == XMPPConnectLogin) {
[_xmppStrem authenticateWithPassword:_password error:nil];
}else if (_xmppConnectType == XMPPConnectRegister)
[_xmppStrem registerWithPassword:_password error:nil];
}
//注册成功,自动登录
- (void)xmppStreamDidRegister:(XMPPStream *)sender {
//转换block类型
_loginSusseccBlock = _registerSuccessBlock;
//登录认证
[_xmppStrem authenticateWithPassword:_password error:nil];
}
//注册失败
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error {
if (_registerFailBlock) {
_registerFailBlock(@"此账户已存在");
}
//断开连接,不断开连接接下来的服务器连接均会失败
[_xmppStrem disconnect];
}
//密码认证成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
if (_loginSusseccBlock) {
_loginSusseccBlock();
}
//上线
[self goOnline];
}
//密码认证失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error {
[_xmppStrem disconnect];
if (_loginFailBlock) {
_loginFailBlock(@"帐号密码错误");
}
}
#pragma mark - 上线
- (void)goOnline {
XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
[_xmppStrem sendElement:presence];
}
#pragma mark - 下线
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
[_xmppStrem sendElement:presence];
//下线必须断开服务器连接
[_xmppStrem disconnect];
}
查询好友列表
- (void)setFriendsListBlock:(FriendsListBlock)block {
//保存block
_friendsListBlock = [block copy];
//创建IQ请求
NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"];
//设置iq请求的三个属性
XMPPJID *jid = _xmppStrem.myJID;
[iq addAttributeWithName:@"from" stringValue:jid.description];
[iq addAttributeWithName:@"type" stringValue:@"get"];
[iq addAttributeWithName:@"id" stringValue:@"roster_1"];
//设置iq请求的子元素
XMPPElement *query = [XMPPElement elementWithName:@"query"];
[query addAttributeWithName:@"xmlns" stringValue:@"jabber:iq:roster"];
[iq addChild:query];
//发送查询请求
[_xmppStrem sendElement:iq];
}
收到查询回传 自动调用
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
//判断iq的元素ID是否为传入的元素ID
if ([iq.elementID isEqualToString:@"roster_1"]) {
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
//获取query结点
NSXMLElement *query = [iq elementForName:@"query"];
for (NSXMLElement *item in query.children) {
User *user = [[User alloc] init];
//设置好友的JID名字和自定义名
user.jid = [item attributeStringValueForName:@"jid"];
user.username = [item attributeStringValueForName:@"name"];
for (NSXMLElement *group in item.children) {
//获取组名
NSString *groupName = [group stringValue];
//获取好友分组
NSMutableArray *groupArray = dic[groupName];
if (groupArray == nil) {
//若没有该好友分组,则创建
groupArray = [[NSMutableArray alloc] init];
[dic setObject:groupArray forKey:groupName];
}
//好友分组添加用户
[groupArray addObject:user];
}
}
//每一次for循环都把好友分组情况通过block传递出去
if (_friendsListBlock) {
_friendsListBlock([dic copy]);
}
}
return YES;
}
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid {
//如果消息或者发给对象为空,则返回
if (text == nil || text.length == 0 || jid == nil || jid.length == 0) {
return;
}
//如果发给对象不含服务器域名@wxhl
NSRange range = [jid rangeOfString:[NSString stringWithFormat:@"@%@", KHostName]];
if (range.location == NSNotFound) {
return;
}
XMPPJID *toJID = [XMPPJID jidWithString:jid];
//创建框架提供的信息元素
XMPPMessage *message = [[XMPPMessage alloc] initWithType:@"chat" to:toJID];
[message addBody:text];
//发送元素
[_xmppStrem sendElement:message];
}
- (void)sendMessage:(NSString *)text toUser:(NSString *)jid {
//判断传入参数是否为空
if (text == nil || text.length == 0 || jid == nil || jid.length == 0) {
return;
}
//jid格式检查 查找jid中是否包含了 @wxhl
NSRange range = [jid rangeOfString:[NSString stringWithFormat:@"@%@", kHostName]];
if (range.location == NSNotFound) {
return;
}
//创建msg节点
NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
//添加属性
XMPPJID *myJID = _xmppStream.myJID;
[message addAttributeWithName:@"from" stringValue:myJID.description];
[message addAttributeWithName:@"to" stringValue:jid];
[message addAttributeWithName:@"type" stringValue:@"chat"];
NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
body.stringValue = text;
//添加子节点
[message addChild:body];
//发送消息
[_xmppStream sendElement:message];
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
//判断消息是否是有效信息
if (message.isChatMessage) {
//保存消息的内容和用户
NSString *body = message.body;
NSString *fromUserName = message.from.user;
//将消息封装成通知的参数
NSDictionary *info = @{@"user" : fromUserName,
@"body" : body
};
//通过发送通知发送收到的消息
[[NSNotificationCenter defaultCenter] postNotificationName:kRecieveMessageNotification object:nil userInfo:info];
}
}
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message {
NSLog(@"消息发送成功");
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error {
NSLog(@"消息发送失败");
}