我們需要與服務(wù)器連接菇夸,可以創(chuàng)建一個(gè)XMPP的管理類(lèi)轨域,負(fù)責(zé)處理客戶端與服務(wù)器端的交互
我們來(lái)創(chuàng)建一個(gè)XMPPManager類(lèi)侠坎,繼承NSObject
因?yàn)閄MPPManager這個(gè)類(lèi)他是負(fù)責(zé)整個(gè)客戶端與服務(wù)器端的即時(shí)通訊,所以他只需要一個(gè)實(shí)例就可以了扶踊,我們來(lái)創(chuàng)建一個(gè)單例泄鹏。
XMPP框架里有個(gè)類(lèi),叫做XMPPStream秧耗,通信管道备籽,他是負(fù)責(zé)客戶端和服務(wù)端的數(shù)據(jù)傳輸
就好比你拿一臺(tái)座機(jī)跟你的朋友打電話一樣,這臺(tái)電話需要一個(gè)電話線才可以
首先我們要引入XMPPFrameWork的框架
然后我們來(lái)創(chuàng)建一個(gè)XMPPStream的對(duì)象 ? 分井,創(chuàng)建完了以后我們要對(duì)他進(jìn)行一個(gè)初始化
創(chuàng)建完這個(gè)對(duì)象后胶台,我們要給他指定服務(wù)器的IP地址,XMPPStream有一個(gè)屬性
叫做hostName杂抽,我們這里定義了一個(gè)宏,叫做kHostName韩脏,我們可以點(diǎn)進(jìn)去看一下
除了服務(wù)器地址外呢缩麸,我們還需要給XMPPStream設(shè)置一個(gè)端口號(hào)
什么是端口號(hào)呢?
我們的服務(wù)器內(nèi)儲(chǔ)存的都是服務(wù)赡矢,可能有sqlite服務(wù)杭朱,email服務(wù)阅仔,或者我們的XMPP服務(wù)
每一個(gè)服務(wù)都有對(duì)應(yīng)的一個(gè)端口號(hào),就好比你出去面試一樣弧械,一家公司告訴你八酒,我們公司在望京SOHO大樓里,幾樓刃唐,幾號(hào)羞迷,這個(gè)望京SOHO就相當(dāng)于是一個(gè)服務(wù)器,里面存儲(chǔ)著的各家公司就好比是服務(wù)画饥,而每家公司都肯定會(huì)有一個(gè)自己的門(mén)牌號(hào)衔瓮,要沒(méi)有這些的話,公司邀請(qǐng)你面試抖甘,告訴你我們?cè)谕㏒OHO热鞍,你來(lái)吧,門(mén)牌號(hào)沒(méi)有衔彻,自己找薇宠,你肯定會(huì)想,逗我玩呢艰额?
所以我們的服務(wù)是必須要有端口號(hào)的澄港,這樣才可以讓我們準(zhǔn)確地找到我們的服務(wù),來(lái)進(jìn)行實(shí)現(xiàn)我們要得功能
我們的XMPPStream有一個(gè)屬性悴晰,叫做hostPort慢睡,我們這里也定義了一個(gè)宏
XMPP使用的openfire他有一個(gè)默認(rèn)的端口是5222,我們把5222設(shè)定為了一個(gè)宏
有了這兩個(gè)之后他就明白你要連接到服務(wù)器的哪個(gè)服務(wù)了
最后我們要當(dāng)前的這個(gè)對(duì)象成為XMPPStream的代理對(duì)象铡溪,因?yàn)槟阋蚍?wù)器發(fā)送連接請(qǐng)求
那么你可能連接成功也可能連接失敗漂辐,和我們的HTTP請(qǐng)求一樣
那么這個(gè)連接成功與失敗需要我們的一個(gè)協(xié)議方法來(lái)告知我們結(jié)果
所以我們要當(dāng)前對(duì)象成為XMPPStream代理對(duì)象
首先我們要遵循XMPPStream的一個(gè)協(xié)議
然后我們添加一個(gè)代理方法
[self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
通常我們使用代理的時(shí)候都是setDelegate 那么一個(gè)對(duì)象只能設(shè)置一個(gè)代理對(duì)象
這里比較特殊,待會(huì)我們就可以看到這里使用添加代理對(duì)象有什么樣的好處
然后我們就可以向服務(wù)器發(fā)送連接請(qǐng)求
我們寫(xiě)一個(gè)方法棕硫,專(zhuān)門(mén)為服務(wù)器發(fā)送連接請(qǐng)求
//連接請(qǐng)求
(void)connectToServer
我們有了連接髓涯,當(dāng)然也不能少了斷開(kāi)方法
//斷開(kāi)連接
(void)disconnectWithServer
連接的時(shí)候我們要進(jìn)行一個(gè)判斷,判斷當(dāng)前是否正在鏈接
[self.xmppStream isConnected];
如果正在連接哈扮,我們斷開(kāi)連接
[self disconnectWithServer];
為什么要這么做呢纬纪?
就比如你現(xiàn)在和你得A朋友正在打電話,但是你又想給C朋友打電話滑肉,那你不得把這邊掛了才能給那邊打過(guò)去嗎包各?
那么斷開(kāi)之后,就可以向服務(wù)器發(fā)送鏈接靶庙,在向服務(wù)器發(fā)送鏈接之前呢
你需要告訴服務(wù)器问畅,你是誰(shuí)
在XMPP框架中呢,有一個(gè)XMPPJID類(lèi),JID呢护姆,是Jabber ID的縮寫(xiě)矾端,因?yàn)槲覀兊腦MPP其實(shí)就是基J于Jabber協(xié)議的基礎(chǔ)開(kāi)發(fā)的,JID就是XMPP中得唯一標(biāo)示
我們可以創(chuàng)建一個(gè)XMPPJID卵皂,我們來(lái)看一下他的初始化方法
XMPPJID *jid = [XMPPJID jidWithUser:(NSString *)domain:(NSString *) resource:(NSString *)];
user就是你得用戶名domain是域名秩铆,配置openfire給他的域名 resource客戶端的來(lái)源,比如你得QQ灯变,比如iPhone或者window或者是Android
我們這里定義的有宏殴玛,domain這里的openfire給的域名一致就可以了。
那我們這里的user給什么呢柒凉?我們這個(gè)用戶名可以使用一個(gè)接口就行了族阅。
XMPPManager里面有一個(gè)方法
- (void)loginWithUser:(NSString *)user password:(NSString *)password
我們把XMPPJID *jid = [XMPPJID jidWithUser:(NSString *)domain:kDomain resource:kResource];寫(xiě)入里面
這個(gè)時(shí)候我們可以把第一個(gè)參數(shù)寫(xiě)為user
我們這個(gè)xmppStream里有個(gè)參數(shù)為myJID 把他等于jid;
然后就可以進(jìn)行連接
NSError *error = nil;
[self.xmppStream connectWithTimeout:30.0f error:&error];
判斷一下我們的錯(cuò)誤信息
if (nil != error )
{
NSLog(@“%s__%d__|鏈接出錯(cuò):%@”,__FUNCTION__,__LINE__,error);
}
進(jìn)行鏈接的時(shí)候會(huì)有兩種結(jié)果膝捞,一種是成功坦刀,一種失敗
那我們需要通過(guò)XMPP的協(xié)議去實(shí)現(xiàn)這兩種方法
第一個(gè)是成功的
//與服務(wù)器鏈接成功
(void)xmppStreamDidConnect:(XMPPStream *)sender
//與服務(wù)器鏈接失敗
(void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
在兩個(gè)方法內(nèi)分別打印一下
NSLog(@“%s__%d__|”,__FUNCTION__,__LINE__);
我們回到我們的登錄頁(yè)面
在登錄按鈕的方法內(nèi)寫(xiě)入我們的登錄方法
[[XMPPManager defaultManager] loginWithUser:userName password:password];
我們來(lái)驗(yàn)證一下,運(yùn)行以后點(diǎn)擊登錄蔬咬,打印的是[XMPPManager xmppStreamDidConnect];
我們看這里是xmppStreamDidConnect
我們點(diǎn)進(jìn)xmppStream代理方法里看一看這個(gè)方法
注釋內(nèi)容為T(mén)his method is called after registration of a new user has successfully finished
翻譯一下為:調(diào)用此方法后注冊(cè)一個(gè)新用戶已經(jīng)成功完成
這里我們的登錄方法內(nèi)還有一個(gè)password沒(méi)有使用鲤遥,我們現(xiàn)在只是向服務(wù)器發(fā)送了鏈接請(qǐng)求
而沒(méi)有去驗(yàn)證自己的身份,這個(gè)時(shí)候就要使用password來(lái)驗(yàn)證
我們?cè)阪溄臃?wù)器成功地方法內(nèi)寫(xiě)一下
[self.xmppStream authenticateWithPassword:(NSString *) error:(NSError *_autoreleasing *)];
這里的password是在
- (void)loginWithUser:(NSString *)user password:(NSString *)password
方法里地林艘,所以我們需要調(diào)用一下這個(gè)方法給傳過(guò)來(lái)盖奈,我們要保存一下
聲明一個(gè)變量
這里這個(gè)驗(yàn)證也是向服務(wù)器發(fā)送驗(yàn)證
自然也有驗(yàn)證結(jié)果,一個(gè)成功一個(gè)失敗
這個(gè)結(jié)果我們還是要傳回登錄界面狐援,倒不如我們?cè)诘卿浗缑嬷苯荧@取
怎么獲取呢钢坦?
我們之前有提到過(guò)
xmppStream是可以添加多個(gè)對(duì)象的,既然我們這個(gè)XMPPManager可以成為他的代理對(duì)象
那我們的登錄界面自然也可以成為他的代理對(duì)象啥酱,我們?cè)诘卿浗缑嫣砑右幌逻@個(gè)代理對(duì)象
我們來(lái)實(shí)現(xiàn)以下他的協(xié)議方法爹凹。
//驗(yàn)證成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
NSLog(@"%s__%d__|",__FUNCTION__,__LINE__);
}
//驗(yàn)證失敗
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
NSLog(@"%s__%d__|驗(yàn)證失敗:%@",__FUNCTION__,__LINE__,error);
}
運(yùn)行以下镶殷,可以看到走的方法是xmppStreamDidAuthenticate禾酱,
證明我們驗(yàn)證成功了。
那我們登錄成功地話绘趋,是不是應(yīng)該把這個(gè)登錄界面dimiss呢颤陶?
在驗(yàn)證成功地方法內(nèi)添加一下dismiss的方法
我們?nèi)绾螌?shí)現(xiàn)登錄過(guò)以后,下次不再出現(xiàn)登錄界面呢陷遮?這個(gè)時(shí)候就需要用到我們數(shù)據(jù)持久化的方法
對(duì)用戶名和密碼進(jìn)行存儲(chǔ)
我們依然在驗(yàn)證成功地方法內(nèi)使用
[[NSUserDefaults standardUserDefaults] setObject:self.userName.text forKey:@"userName"];
[[NSUserDefaults standardUserDefaults] setObject:self.passWord.text forKey:@“password"];
先獲取我們的用戶名和密碼
[[NSUserDefaults standardUserDefaults] synchronize];
然后進(jìn)行保存滓走。(保存到磁盤(pán)上)
在下次進(jìn)入應(yīng)用的時(shí)候應(yīng)該先判斷我們的用戶名
首先用一個(gè)bool方法來(lái)獲取一下我們的用戶名
然后再進(jìn)行一個(gè)判斷,判斷我們是否已經(jīng)登錄
代碼如下
我們還需要把當(dāng)前對(duì)象添加一個(gè)代理帽馋,遵循代理方法去進(jìn)行驗(yàn)證我們的登錄是否成功
以上是我們的登錄功能搅方。