XMPP登录注册1
1. 环境准备:openfire + mysql 5.1.6 + Xcode5 + XMPP.Framework (至于环境的配置, 请自己百度, 推荐: http://www.cnblogs.com/xiaodao/archive/2013/04/05/3000554.html)
2. cocoapods
1 platform :ios, '7.0' 2 pod "XMPPFramework", "~>3.6.4"
3.工程: ARC + COREDATA + XIB(Storyboard)
4.直奔重点: XMPP工具单例
1. 首先, 创建一个Infromation.h 文件 用来存放我们需要的一些基本信息,比如host之类的。 然后把这个头文件导入pch文件中 注意我的Domains 后边多一个@
1 #ifndef ADXMPP_BE_Information_h 2 #define ADXMPP_BE_Information_h 3 4 #define SERVER @"127.0.0.1" 5 #define DOMAINS @"@127.0.0.1" 6 7 #endif
2. 创建ADXMPPConn 类、 开始编辑我们的XMPP连接、 登录、 注册核心代码
ADXMPPConn.h
1 // 2 // ADXMPPConn.h 3 // ADXMPP_BE 4 // 5 // Created by Dylan on 14-10-8. 6 // Copyright (c) 2014年 Dylan. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import <XMPP.h> 11 12 /** 13 用来判断当前用户在进行什么操作 14 */ 15 typedef enum { 16 LOGIN, 17 REGISTER 18 }USER_TYPE; 19 20 /*! 21 * @Author Dylan. 22 * 23 * Callbacl Block 24 */ 25 typedef void(^connectSuccess)(); 26 typedef void(^AuthenticateFailure)(id); 27 28 typedef void(^registerSuccess)(); 29 typedef void(^registerFailure)(id); 30 31 @interface ADXMPPConn : NSObject <XMPPStreamDelegate> 32 33 /*! 34 * @Author Dylan. 35 * 36 * xmppStream 37 */ 38 @property (nonatomic, strong) XMPPStream * xmppStream; 39 40 /*! 41 * @Author Dylan. 42 * 43 * Username, Password 44 */ 45 @property (nonatomic, strong) NSString * userName; 46 @property (nonatomic, strong) NSString * passWord; 47 48 /*! 49 * @Author Dylan. UserType 50 */ 51 @property (nonatomic) USER_TYPE USERTYPE; 52 53 /*! 54 * @Author Dylan. 55 * 56 * Methods 57 */ 58 #pragma mark - Methods 59 60 /*! 61 * shareInstance 62 */ 63 + (instancetype)shareInstance; 64 65 /*! 66 * setup xmppStream 67 */ 68 - (void) setupXmppStream; 69 70 /*! 71 * on/off line 72 */ 73 - (void) online; 74 - (void) offline; 75 76 /*! 77 * connection/register 78 */ 79 - (BOOL)connectionWithUserName: (NSString *)userName 80 passWord: (NSString *)passWord 81 success: (connectSuccess)Success 82 failure: (AuthenticateFailure)Failure; 83 84 - (void)registerWithUserName: (NSString *)userName 85 passWord: (NSString *)passWord 86 success: (registerSuccess)Success 87 failure: (registerFailure)Failure; 88 89 @end
ADXMPPConn.m
1 // 2 // ADXMPPConn.m 3 // ADXMPP_BE 4 // 5 // Created by Dylan on 14-10-8. 6 // Copyright (c) 2014年 Dylan. All rights reserved. 7 // 8 9 #import "ADXMPPConn.h" 10 11 @interface ADXMPPConn () 12 13 /*! 14 * @Author Dylan. 15 * 16 * Callback Block 17 */ 18 @property (nonatomic, copy) connectSuccess connSuccess; 19 @property (nonatomic, copy) AuthenticateFailure authenFailure; 20 21 @property (nonatomic, copy) registerSuccess regisSuccess; 22 @property (nonatomic, copy) registerFailure regisFailure; 23 24 @end 25 26 // shareInstance 27 static ADXMPPConn * xmppConn; 28 29 @implementation ADXMPPConn 30 31 #pragma mark shareInstance 32 + (instancetype)shareInstance { 33 static dispatch_once_t onceToken; 34 dispatch_once(&onceToken, ^{ 35 xmppConn = [[self alloc] init]; 36 }); 37 38 return xmppConn; 39 } 40 41 #pragma mark - Methods 42 - (void)setupXmppStream { 43 self.xmppStream = [[XMPPStream alloc] init]; 44 [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; 45 } 46 47 #pragma mark on/off line 48 - (void)online { 49 XMPPPresence * presence = [XMPPPresence presence]; 50 [self.xmppStream sendElement:presence]; 51 } 52 53 - (void)offline { 54 XMPPPresence * presence = [XMPPPresence presenceWithType:@"unavailable"]; 55 [self.xmppStream sendElement:presence]; 56 [self.xmppStream disconnect]; 57 } 58 59 #pragma mark connection 60 - (BOOL)connectionWithUserName:(NSString *)userName passWord:(NSString *)passWord success:(connectSuccess)Success failure:(AuthenticateFailure)Failure { 61 62 // setup xmppStream 63 [self setupXmppStream]; 64 65 // get username, password 66 self.userName = userName; 67 self.passWord = passWord; 68 69 // set callback block 70 self.connSuccess = Success; 71 self.authenFailure = Failure; 72 73 if ([self.xmppStream isConnected]) { 74 return YES; 75 } 76 77 if (userName == nil) { 78 return NO; 79 } 80 81 // setJID 82 [self.xmppStream setMyJID:[XMPPJID jidWithString:userName]]; 83 [self.xmppStream setHostName:SERVER]; 84 85 NSError * error = nil; 86 if (![self.xmppStream connectWithTimeout:30 error:&error]) { 87 NSLog(@"%@", [error localizedDescription]); 88 Failure(error); 89 return NO; 90 } 91 92 return YES; 93 } 94 95 - (void)registerWithUserName:(NSString *)userName passWord:(NSString *)passWord success:(registerSuccess)Success failure:(registerFailure)Failure { 96 97 // set user type 98 self.USERTYPE = REGISTER; 99 100 // set username, password 101 self.userName = [userName stringByAppendingString:DOMAINS]; 102 self.passWord = passWord; 103 104 self.regisSuccess = Success; 105 self.regisFailure = Failure; 106 107 [self connectionWithUserName:self.userName passWord:passWord success:Success failure:Failure]; 108 } 109 110 #pragma mark - delegateMethods 111 - (void)xmppStreamDidConnect:(XMPPStream *)sender {113 114 NSError * error = nil; 115 116 // kind of user type 117 if (self.USERTYPE == REGISTER) { 118 119 // registe 120 [self.xmppStream setMyJID:[XMPPJID jidWithString:self.userName]]; 121 NSError * error = nil; 122 if (![self.xmppStream registerWithPassword:self.passWord error:&error]) { 123 self.regisFailure([error localizedDescription]); 124 } 125 126 } else { 127 // authenticate 128 [self.xmppStream authenticateWithPassword:self.passWord error:&error]; 129 if (error != nil) { 130 self.authenFailure([error localizedDescription]); 131 } 132 } 133 } 134 135 // dis connect 136 - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { 137 NSLog(@"%@", [error localizedDescription]); 138 } 139 140 // authenticate 141 - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { 142 self.authenFailure(error); 143 } 144 145 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { 146 // online 147 [self online]; 148 self.connSuccess(); 149 } 150 151 // regist 152 - (void)xmppStreamDidRegister:(XMPPStream *)sender { 153 self.regisSuccess(); 154 } 155 156 - (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error { 157 self.regisFailure(error); 158 } 159 160 @end
XMPP收发消息2
Message:
接着写
.h
1 /*! 2 * @Author Dylan. 3 * 4 * callback Block 5 */ 6 typedef void(^sendSuccess)(); 7 typedef void(^sendFailure)(id); 8 9 /*! 10 * sendMessageBy model 11 */ 12 - (void)sendMessage: (ADMessageModel *)message 13 sendSuccess: (sendSuccess)success 14 sendFailure: (sendFailure)failure; 15 16 /*! 17 * @Author Dylan. 18 * 19 * unRead Msg 20 */ 21 @property (nonatomic, strong) NSMutableDictionary * unReadMsg; 22 23 /*! 24 * @Author Dylan. 25 * 26 * new Msg 27 */ 28 @property (nonatomic, copy) void (^newMessage) (id); 29 30 31 @end
.m
1 #pragma mark - initData 2 - (void)initData { 3 // 可做数据持久化 4 self.unReadMsg = [NSMutableDictionary dictionary]; 5 } 6 7 #pragma mark Methods 8 - (void)sendMessage: (ADMessageModel *)message 9 sendSuccess: (sendSuccess)success 10 sendFailure: (sendFailure)failure { 11 12 // set callback block 13 self.success = success; 14 self.failure = failure; 15 16 NSXMLElement * body = [NSXMLElement elementWithName:@"body"]; 17 [body setStringValue:message.body]; 18 19 //生成XML消息文档 20 NSXMLElement *mes = [NSXMLElement elementWithName:@"message"]; 21 //消息类型 22 [mes addAttributeWithName:@"type" stringValue:@"chat"]; 23 //发送给谁 24 [mes addAttributeWithName:@"to" stringValue:message.to]; 25 //由谁发送 26 [mes addAttributeWithName:@"from" stringValue:message.from]; 27 //组合 28 [mes addChild:body]; 29 //发送消息 30 [[self xmppStream] sendElement:mes]; 31 } 32 33 #pragma mark - delegeteMethods 34 - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { 35 36 NSString * body = [[message elementForName:@"body"] stringValue]; 37 NSString * from = [[message attributeForName:@"from"] stringValue]; 38 39 if (body != nil) { 40 41 NSMutableDictionary * msgDict = [NSMutableDictionary dictionary]; 42 ADMessageModel * model = [[ADMessageModel alloc] init]; 43 model.body = body; 44 model.from = from; 45 [msgDict setValue:model forKey:[ADCurrentTime getCurrentTime]]; 46 47 if ([from isEqualToString:[[NSUserDefaults standardUserDefaults] stringForKey:CURRENT_CHAT]]) { 48 49 self.newMessage(msgDict); 50 } else { 51 // not current chat 52 if ([_unReadMsg.allKeys containsObject:from]) { 53 [_unReadMsg[from] addObject:model]; 54 } else { 55 [_unReadMsg setValue:[NSMutableArray arrayWithObject:msgDict] forKey:from]; 56 } 57 } 58 59 } 60 } 61 62 @end
XMPP好友列表3
// Roster
我们继续写 获取好友列表
.h
1 /*! 2 * @Author Dylan. 3 * 4 * Roster 5 */ 6 7 typedef void (^refreshRosterListFailure) (id); 8 typedef void (^Rosterlist) (id); 9 10 /*! 11 * @Author Dylan. 12 * 13 * request for roster list. IQ 14 */ 15 - (void)refreshRosterList: (Rosterlist)success 16 failure: (refreshRosterListFailure)failure; 17 @property (nonatomic, strong) NSMutableDictionary * rosterDict;
.m
1 #pragma mark - rosterList 2 3 - (void)initRosterlist { 4 self.rosterDict = [NSMutableDictionary dictionary]; 5 } 6 7 - (void)refreshRosterList: (Rosterlist)success 8 failure: (refreshRosterListFailure)failure { 9 10 // call back 11 self.refreshSuccess = success; 12 self.refreshFailure = failure; 13 14 NSXMLElement * query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:roster"]; 15 NSXMLElement * iq = [NSXMLElement elementWithName:@"iq"]; 16 17 XMPPJID * myJID = self.xmppStream.myJID; 18 [iq addAttributeWithName:@"from" stringValue:myJID.description]; 19 [iq addAttributeWithName:@"to" stringValue:myJID.domain]; 20 [iq addAttributeWithName:@"id" stringValue:@"123456"]; 21 [iq addAttributeWithName:@"type" stringValue:@"get"]; 22 [iq addChild:query]; 23 24 [self.xmppStream sendElement:iq]; 25 } 26 27 - (void)xmppStream:(XMPPStream *)sender didFailToSendIQ:(XMPPIQ *)iq error:(NSError *)error { 28 self.refreshFailure(error); 29 } 30 31 // get user list 32 - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { 33 34 // kind of result 35 if ([@"result" isEqualToString:iq.type]) { 36 NSXMLElement * query = iq.childElement; 37 38 if ([@"query" isEqualToString:query.name]) { 39 NSArray * items = [query children]; 40 for (NSXMLElement * item in items) { 41 NSString * jid = [item attributeStringValueForName:@"jid"]; 42 XMPPJID * xmppJID = [XMPPJID jidWithString:jid]; 43 [_rosterDict setValue:xmppJID forKey:jid]; 44 } 45 } 46 // block 47 self.refreshSuccess(_rosterDict); 48 return YES; 49 } 50 51 NSLog(@"get iq error"); 52 return NO; 53 } 54 55 56 @end
// 顺便写出在点m文件中我写的回掉Block 的属性
1 @interface ADXMPPConn () 2 3 /*! 4 * @Author Dylan. 5 * 6 * Call back Block 7 */ 8 @property (nonatomic, copy) connectSuccess connSuccess; 9 @property (nonatomic, copy) AuthenticateFailure authenFailure; 10 11 @property (nonatomic, copy) registerSuccess regisSuccess; 12 @property (nonatomic, copy) registerFailure regisFailure; 13 14 /*! 15 * call back block 16 */ 17 @property (nonatomic, copy) sendSuccess success; 18 @property (nonatomic, copy) sendFailure failure; 19 20 /*! 21 * call back block 22 */ 23 @property (nonatomic, copy) refreshRosterListFailure refreshFailure; 24 @property (nonatomic, copy) Rosterlist refreshSuccess; 25 26 @end
xmpp好友状态4
// 实现好友状态的获取 - 在线、离线 别的状态自己去写一下判断和回掉就好
.h
1 /*! 2 * @Author Dylan. 3 * 4 * Paresence 5 */ 6 typedef void (^userGoOnline) (NSString *); 7 typedef void (^userGoOffline) (NSString *); 8 9 - (void)refreshRosterPresence: (userGoOnline)online 10 offline: (userGoOffline)offline;
.m
1 #pragma mark presence 2 - (void)refreshRosterPresence: (userGoOnline)online 3 offline: (userGoOffline)offline { 4 5 self.rosterOnline = online; 6 self.rosterOffline = offline; 7 } 8 9 - (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence { 10 11 // get presence type 12 NSString * presenceType = [presence type]; 13 NSString * userID = [[sender myJID] user]; 14 15 NSString * presencrFromUser = [[presence from] user]; 16 if (![presencrFromUser isEqualToString:userID]) { 17 if ([presenceType isEqualToString:@"available"]) { 18 self.rosterOnline(presencrFromUser); 19 } else if ([presenceType isEqualToString:@"unavailable"]) { 20 self.rosterOffline(presencrFromUser); 21 } 22 } 23 }
补上Block回掉申明
1 /*! 2 * call back block 3 */ 4 @property (nonatomic, copy) userGoOnline rosterOnline; 5 @property (nonatomic, copy) userGoOffline rosterOffline;
xmpp好友请求5
实现好友请求
.m
1 #pragma mark - rosterHandle 2 3 // initRoster 4 - (void)initRoster { 5 self.xmppRosterMemory = [[XMPPRosterMemoryStorage alloc] init]; 6 self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:self.xmppRosterMemory]; 7 [_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()]; 8 [_xmppRoster activate:self.xmppStream]; 9 } 10 11 - (void)addFriend: (NSString *)accountName { 12 [_xmppRoster addUser:[XMPPJID jidWithString:[accountName stringByAppendingString:DOMAINS]] withNickname:nil]; 13 } 14 15 - (void)removeFriend: (NSString *)accountName { 16 [_xmppRoster removeUser:[XMPPJID jidWithString:[accountName stringByAppendingString:DOMAINS]]]; 17 } 18 19 // call back 20 - (void)dealWithFriendAsk: (BOOL)isAgree 21 accountName: (NSString *)accountName { 22 XMPPJID * jid=[XMPPJID jidWithString:[NSString stringWithFormat:@"%@%@",accountName,DOMAINS]]; 23 if(isAgree){ 24 [self.xmppRoster acceptPresenceSubscriptionRequestFrom:jid andAddToRoster:NO]; 25 }else{ 26 [self.xmppRoster rejectPresenceSubscriptionRequestFrom:jid]; 27 } 28 29 } 30 31 #pragma mark addFriendDelegateMethods 32 - (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence { 33 34 NSString *presenceFromUser =[NSString stringWithFormat:@"%@", [[presence from] user]]; 35 if (self.acceptOrDenyFriend != nil) { 36 BOOL isAgree = self.acceptOrDenyFriend(presenceFromUser); 37 [self dealWithFriendAsk:isAgree accountName:presenceFromUser]; 38 } 39 } 40 41 @end
.h
1 /*! 2 * @Author Dylan. 3 * 4 * addRoster. 5 */ 6 // if you want to deny or add friend. please call this block 7 @property (nonatomic, copy) BOOL (^acceptOrDenyFriend) (NSString *); 8 @property (nonatomic, strong) XMPPRoster * xmppRoster; 9 10 /*! 11 * @Author Dylan. Methods 12 */ 13 - (void)addFriend: (NSString *)accountName; 14 - (void)removeFriend: (NSString *)accountName;
XMPP教学小结1
到这里、 我们封装了XMPP 登录、 注册、 好友列表获取、 好友状态获取、 信息的收发、
应该去测试一下了 、 我这里把最简单的测试办法扔到这里、 大家可以看一下 。
1 // 2 // ADViewController.m 3 // ADXMPP_BE 4 // 5 // Created by Dylan on 14-10-8. 6 // Copyright (c) 2014年 Dylan. All rights reserved. 7 // 8 9 #import "ADViewController.h" 10 #import "ADMessageModel.h" 11 12 @interface ADViewController () 13 14 @end 15 16 @implementation ADViewController 17 18 - (void)viewDidLoad 19 { 20 [super viewDidLoad]; 21 22 23 // testLogin 24 [XMPPHANDLE connectionWithUserName:@"dylan@127.0.0.1" passWord:@"admin" success:^{ 25 NSLog(@"success"); 26 27 [XMPPHANDLE refreshRosterPresence:^(NSString * userID) { 28 29 NSLog(@"%@%@", userID, DOMAINS); 30 } offline:^(NSString * userID) { 31 32 NSLog(@"%@%@", userID, DOMAINS); 33 }]; 34 35 [XMPPHANDLE refreshRosterList:^(id dict) { 36 NSLog(@"%@", dict); 37 38 } failure:^(id error) { 39 NSLog(@"%@", error); 40 }]; 41 42 // testMsg 43 [[NSUserDefaults standardUserDefaults] setValue:@"alice@127.0.0.1/xueyulundeMacBook-Pro" forKey:CURRENT_CHAT]; 44 [XMPPHANDLE setNewMessage:^(id dict) { 45 NSLog(@"%@", dict); 46 }]; 47 48 ADMessageModel * model = [[ADMessageModel alloc] init]; 49 model.from = [NSString stringWithFormat:@"%@", XMPPHANDLE.xmppStream.myJID]; 50 model.to = [[NSUserDefaults standardUserDefaults] stringForKey:CURRENT_CHAT]; 51 model.body = @"Hello"; 52 53 [XMPPHANDLE sendMessage:model sendSuccess:^{ 54 55 NSLog(@"send success"); 56 57 } sendFailure:^(id error) { 58 NSLog(@"%@", error); 59 }]; 60 61 } failure:^(id error) { 62 NSLog(@"error"); 63 }]; 64 65 // testRegis 66 // [XMPPHANDLE registerWithUserName:@"test" passWord:@"admin" success:^{ 67 // NSLog(@"register success"); 68 // } failure:^(id error) { 69 // NSLog(@"%@", error); 70 // }]; 71 } 72 73 - (void)didReceiveMemoryWarning 74 { 75 [super didReceiveMemoryWarning]; 76 } 77 78 @end
特别需要注意的是代码的执行先后顺序。
代理执行方法的先后顺序
保证自己的Block方法体可以被寻找到