1.建立一個新工程html
2.導入XMPP框架git
最新的XMPP框架下載地址:https://github.com/robbiehanson/XMPPFrameworkgithub
將XMPP的幾個文件夾拖進工程中,須要的文件以下:服務器
而後把Sample_XMPPFramework.h更名爲XMPPFramework.h框架
接下來導入兩個依賴庫:libresolv.dylib和libxml2.dylib,而後添加header search:dom
再添加一個pch文件socket
在pch文件中添加以下代碼:工具
#ifdef __OBJC__ #import <UIKit/UIKit.h> #import "XMPPFramework.h" #endif再而後設置工程的pch文件
$SRCROOT後面是項目名/pch文件名。post
作完以上步驟,項目就能夠編譯成功啦!atom
如今開始搭建項目的登陸界面:
首先封裝一個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]; } }
下載地址:點擊下載