我們需要與服務(wù)器連接,可以創(chuàng)建一個XMPP的管理類,負責處理客戶端與服務(wù)器端的交互
我們來創(chuàng)建一個XMPPManager類,繼承NSObject
因為XMPPManager這個類他是負責整個客戶端與服務(wù)器端的即時通訊,所以他只需要一個實例就可以了,我們來創(chuàng)建一個單例。

XMPP框架里有個類,叫做XMPPStream,通信管道,他是負責客戶端和服務(wù)端的數(shù)據(jù)傳輸
就好比你拿一臺座機跟你的朋友打電話一樣,這臺電話需要一個電話線才可以
首先我們要引入XMPPFrameWork的框架
然后我們來創(chuàng)建一個XMPPStream的對象 ? ,創(chuàng)建完了以后我們要對他進行一個初始化
創(chuàng)建完這個對象后,我們要給他指定服務(wù)器的IP地址,XMPPStream有一個屬性
叫做hostName,我們這里定義了一個宏,叫做kHostName,我們可以點進去看一下
除了服務(wù)器地址外呢,我們還需要給XMPPStream設(shè)置一個端口號
什么是端口號呢?
我們的服務(wù)器內(nèi)儲存的都是服務(wù),可能有sqlite服務(wù),email服務(wù),或者我們的XMPP服務(wù)
每一個服務(wù)都有對應(yīng)的一個端口號,就好比你出去面試一樣,一家公司告訴你,我們公司在望京SOHO大樓里,幾樓,幾號,這個望京SOHO就相當于是一個服務(wù)器,里面存儲著的各家公司就好比是服務(wù),而每家公司都肯定會有一個自己的門牌號,要沒有這些的話,公司邀請你面試,告訴你我們在望京SOHO,你來吧,門牌號沒有,自己找,你肯定會想,逗我玩呢?
所以我們的服務(wù)是必須要有端口號的,這樣才可以讓我們準確地找到我們的服務(wù),來進行實現(xiàn)我們要得功能
我們的XMPPStream有一個屬性,叫做hostPort,我們這里也定義了一個宏
XMPP使用的openfire他有一個默認的端口是5222,我們把5222設(shè)定為了一個宏
有了這兩個之后他就明白你要連接到服務(wù)器的哪個服務(wù)了
最后我們要當前的這個對象成為XMPPStream的代理對象,因為你要向服務(wù)器發(fā)送連接請求
那么你可能連接成功也可能連接失敗,和我們的HTTP請求一樣
那么這個連接成功與失敗需要我們的一個協(xié)議方法來告知我們結(jié)果
所以我們要當前對象成為XMPPStream代理對象
首先我們要遵循XMPPStream的一個協(xié)議
然后我們添加一個代理方法
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
通常我們使用代理的時候都是setDelegate 那么一個對象只能設(shè)置一個代理對象
這里比較特殊,待會我們就可以看到這里使用添加代理對象有什么樣的好處
然后我們就可以向服務(wù)器發(fā)送連接請求
我們寫一個方法,專門為服務(wù)器發(fā)送連接請求
//連接請求
(void)connectToServer
我們有了連接,當然也不能少了斷開方法
//斷開連接
(void)disconnectWithServer
連接的時候我們要進行一個判斷,判斷當前是否正在鏈接
[self.xmppStream isConnected];
如果正在連接,我們斷開連接
[self disconnectWithServer];
為什么要這么做呢?
就比如你現(xiàn)在和你得A朋友正在打電話,但是你又想給C朋友打電話,那你不得把這邊掛了才能給那邊打過去嗎?
那么斷開之后,就可以向服務(wù)器發(fā)送鏈接,在向服務(wù)器發(fā)送鏈接之前呢
你需要告訴服務(wù)器,你是誰
在XMPP框架中呢,有一個XMPPJID類,JID呢,是Jabber ID的縮寫,因為我們的XMPP其實就是基J于Jabber協(xié)議的基礎(chǔ)開發(fā)的,JID就是XMPP中得唯一標示
我們可以創(chuàng)建一個XMPPJID,我們來看一下他的初始化方法
XMPPJID *jid = [XMPPJID jidWithUser:(NSString *)domain:(NSString *) resource:(NSString *)];
user就是你得用戶名domain是域名,配置openfire給他的域名 resource客戶端的來源,比如你得QQ,比如iPhone或者window或者是Android
我們這里定義的有宏,domain這里的openfire給的域名一致就可以了。
那我們這里的user給什么呢?我們這個用戶名可以使用一個接口就行了。
XMPPManager里面有一個方法
- (void)loginWithUser:(NSString *)user password:(NSString *)password
我們把XMPPJID *jid = [XMPPJID jidWithUser:(NSString *)domain:kDomain resource:kResource];寫入里面
這個時候我們可以把第一個參數(shù)寫為user
我們這個xmppStream里有個參數(shù)為myJID 把他等于jid;
然后就可以進行連接
NSError *error = nil;
[self.xmppStream connectWithTimeout:30.0f error:&error];
判斷一下我們的錯誤信息
if (nil != error )
{
NSLog(@“%s__%d__|鏈接出錯:%@”,__FUNCTION__,__LINE__,error);
}
進行鏈接的時候會有兩種結(jié)果,一種是成功,一種失敗
那我們需要通過XMPP的協(xié)議去實現(xiàn)這兩種方法
第一個是成功的
//與服務(wù)器鏈接成功
(void)xmppStreamDidConnect:(XMPPStream *)sender
//與服務(wù)器鏈接失敗
(void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
在兩個方法內(nèi)分別打印一下
NSLog(@“%s__%d__|”,__FUNCTION__,__LINE__);
我們回到我們的登錄頁面
在登錄按鈕的方法內(nèi)寫入我們的登錄方法
[[XMPPManager defaultManager] loginWithUser:userName password:password];
我們來驗證一下,運行以后點擊登錄,打印的是[XMPPManager xmppStreamDidConnect];
我們看這里是xmppStreamDidConnect
我們點進xmppStream代理方法里看一看這個方法
注釋內(nèi)容為This method is called after registration of a new user has successfully finished
翻譯一下為:調(diào)用此方法后注冊一個新用戶已經(jīng)成功完成
這里我們的登錄方法內(nèi)還有一個password沒有使用,我們現(xiàn)在只是向服務(wù)器發(fā)送了鏈接請求
而沒有去驗證自己的身份,這個時候就要使用password來驗證
我們在鏈接服務(wù)器成功地方法內(nèi)寫一下
[self.xmppStream authenticateWithPassword:(NSString *) error:(NSError *_autoreleasing *)];
這里的password是在
- (void)loginWithUser:(NSString *)user password:(NSString *)password
方法里地,所以我們需要調(diào)用一下這個方法給傳過來,我們要保存一下
聲明一個變量
這里這個驗證也是向服務(wù)器發(fā)送驗證
自然也有驗證結(jié)果,一個成功一個失敗
這個結(jié)果我們還是要傳回登錄界面,倒不如我們在登錄界面直接獲取

怎么獲取呢?
我們之前有提到過
xmppStream是可以添加多個對象的,既然我們這個XMPPManager可以成為他的代理對象
那我們的登錄界面自然也可以成為他的代理對象,我們在登錄界面添加一下這個代理對象
我們來實現(xiàn)以下他的協(xié)議方法。
//驗證成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
NSLog(@"%s__%d__|",__FUNCTION__,__LINE__);
}
//驗證失敗
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
NSLog(@"%s__%d__|驗證失敗:%@",__FUNCTION__,__LINE__,error);
}
運行以下,可以看到走的方法是xmppStreamDidAuthenticate,
證明我們驗證成功了。
那我們登錄成功地話,是不是應(yīng)該把這個登錄界面dimiss呢?
在驗證成功地方法內(nèi)添加一下dismiss的方法
我們?nèi)绾螌崿F(xiàn)登錄過以后,下次不再出現(xiàn)登錄界面呢?這個時候就需要用到我們數(shù)據(jù)持久化的方法
對用戶名和密碼進行存儲
我們依然在驗證成功地方法內(nèi)使用
[[NSUserDefaults standardUserDefaults] setObject:self.userName.text forKey:@"userName"];
[[NSUserDefaults standardUserDefaults] setObject:self.passWord.text forKey:@“password"];

先獲取我們的用戶名和密碼
[[NSUserDefaults standardUserDefaults] synchronize];
然后進行保存。(保存到磁盤上)
在下次進入應(yīng)用的時候應(yīng)該先判斷我們的用戶名
首先用一個bool方法來獲取一下我們的用戶名
然后再進行一個判斷,判斷我們是否已經(jīng)登錄
代碼如下
我們還需要把當前對象添加一個代理,遵循代理方法去進行驗證我們的登錄是否成功
以上是我們的登錄功能。