iOS 的 XMPPFramework 简介
XMPPFramework是一個OS X/iOS平臺的開源項目,使用Objective-C實現(xiàn)了XMPP協(xié)議(RFC-3920),同時還提供了用于讀寫XML的工具,大大簡化了基于XMPP的通信應(yīng)用的開發(fā)。
1. 登錄和好友上下線
1.1XMPP中常用對象們
-
XMPPStream:xmpp基礎(chǔ)服務(wù)類
-
XMPPRoster:好友列表類
-
XMPPRosterCoreDataStorage:好友列表(用戶賬號)在core data中的操作類
-
XMPPvCardCoreDataStorage:好友名片(昵稱,簽名,性別,年齡等信息)在core data中的操作類
-
XMPPvCardTemp:好友名片實體類,從數(shù)據(jù)庫里取出來的都是它
-
xmppvCardAvatarModule:好友頭像
-
XMPPReconnect:如果失去連接,自動重連
-
XMPPRoom:提供多用戶聊天支持
-
XMPPPubSub:發(fā)布訂閱
1.2登錄操作,也就是連接xmpp服務(wù)器
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -?(void)connect?{ ????if?(self.xmppStream?==?nil)?{ ????????self.xmppStream?=?[[XMPPStream?alloc]?init]; ????????[self.xmppStream?addDelegate:self?delegateQueue:dispatch_get_main_queue()]; ????} ????if?(![self.xmppStream?isConnected])?{ ????????NSString?*username?=?[[NSUserDefaults?standardUserDefaults]?objectForKey:@"username"]; ????????XMPPJID?*jid?=?[XMPPJID?jidWithUser:username?domain:@"lizhen"?resource:@"Ework"]; ????????[self.xmppStream?setMyJID:jid]; ????????[self.xmppStream?setHostName:@"10.4.125.113"]; ????????NSError?*error?=?nil; ????????if?(![self.xmppStream?connect:&error])?{ ????????????NSLog(@"Connect?Error:?%@",?[[error?userInfo]?description]); ????????} ????} } |
connect成功之后會依次調(diào)用XMPPStreamDelegate的方法,首先調(diào)用
| 1 2 3 | -?(void)xmppStream:(XMPPStream?*)sender?socketDidConnect:(GCDAsyncSocket?*)socket ... |
然后
| 1 | -?(void)xmppStreamDidConnect:(XMPPStream?*)sender |
在該方法下面需要使用xmppStream 的authenticateWithPassword方法進行密碼驗證,成功的話會響應(yīng)delegate的方法,就是下面這個
| 1 | -?(void)xmppStreamDidAuthenticate:(XMPPStream?*)sender |
1.3上線
實現(xiàn)?- (void)xmppStreamDidAuthenticate:(XMPPStream?*)sender?委托方法
| 1 2 3 4 | -?(void)xmppStreamDidAuthenticate:(XMPPStream?*)sender?{ ????XMPPPresence?*presence?=?[XMPPPresence?presenceWithType:@"available"]; ????[self.xmppStream?sendElement:presence]; } |
1.4退出并斷開連接
| 1 2 3 4 5 6 | -?(void)disconnect?{ ????XMPPPresence?*presence?=?[XMPPPresence?presenceWithType:@"unavailable"]; ????[self.xmppStream?sendElement:presence]; ?????? ????[self.xmppStream?disconnect]; } |
1.5好友狀態(tài)
獲取好友狀態(tài),通過實現(xiàn)?
| 1 2 3 | -?(void)xmppStream:(XMPPStream?*)sender?didReceivePresence:(XMPPPresence?*)presence ... |
方法,當(dāng)接收到 presence 標(biāo)簽的內(nèi)容時,XMPPFramework 框架回調(diào)該方法?
一個 presence 標(biāo)簽的格式一般如下:
presence 的狀態(tài):
-
available 上線
-
away 離開
-
do not disturb 忙碌
-
unavailable 下線
| 1 2 3 4 5 6 7 8 9 10 11 | -?(void)xmppStream:(XMPPStream?*)sender?didReceivePresence:(XMPPPresence?*)presence?{ ????NSString?*presenceType?=?[presence?type]; ????NSString?*presenceFromUser?=?[[presence?from]?user]; ????if?(![presenceFromUser?isEqualToString:[[sender?myJID]?user]])?{ ????????if?([presenceType?isEqualToString:@"available"])?{ ????????????// ????????}?else?if?([presenceType?isEqualToString:@"unavailable"])?{ ????????????// ????????} ????} } |
2. 接收消息和發(fā)送消息
2.1接收消息
通過實現(xiàn)?
| 1 | -?(void)xmppStream:(XMPPStream?*)sender?didReceiveMessage:(XMPPMessage?*)message; |
方法
當(dāng)接收到 message 標(biāo)簽的內(nèi)容時,XMPPFramework 框架回調(diào)該方法
根據(jù) XMPP 協(xié)議,消息體的內(nèi)容存儲在標(biāo)簽 body 內(nèi)
| 1 2 3 | -?(void)xmppStream:(XMPPStream?*)sender?didReceiveMessage:(XMPPMessage?*)message?{ ????NSString?*messageBody?=?[[message?elementForName:@"body"]?stringValue]; } |
2.2發(fā)送消息
發(fā)送消息,我們需要根據(jù) XMPP 協(xié)議,將數(shù)據(jù)放到標(biāo)簽內(nèi),例如:
| 1 2 3 4 5 6 7 8 9 10 | -?(void)sendMessage:(NSString?*)?message?toUser:(NSString?*)?user?{ ????NSXMLElement?*body?=?[NSXMLElement?elementWithName:@"body"]; ????[body?setStringValue:message]; ????NSXMLElement?*message?=?[NSXMLElement?elementWithName:@"message"]; ????[message?addAttributeWithName:@"type"?stringValue:@"chat"]; ????NSString?*to?=?[NSString?stringWithFormat:@"%@@example.com",?user]; ????[message?addAttributeWithName:@"to"?stringValue:to]; ????[message?addChild:body]; ????[self.xmppStream?sendElement:message]; } |
3. 獲取好友信息和刪除好友
3.1好友列表和好友名片
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [_xmppRoster?fetchRoster];//獲取好友列表 //獲取到一個好友節(jié)點 -?(void)xmppRoster:(XMPPRoster?*)sender?didRecieveRosterItem:(NSXMLElement?*)item //獲取完好友列表 -?(void)xmppRosterDidEndPopulating:(XMPPRoster?*)sender //到服務(wù)器上請求聯(lián)系人名片信息 -?(void)fetchvCardTempForJID:(XMPPJID?*)jid; //請求聯(lián)系人的名片,如果數(shù)據(jù)庫有就不請求,沒有就發(fā)送名片請求 -?(void)fetchvCardTempForJID:(XMPPJID?*)jid?ignoreStorage:(BOOL)ignoreStorage; //獲取聯(lián)系人的名片,如果數(shù)據(jù)庫有就返回,沒有返回空,并到服務(wù)器上抓取 -?(XMPPvCardTemp?*)vCardTempForJID:(XMPPJID?*)jid?shouldFetch:(BOOL)shouldFetch; //更新自己的名片信息 -?(void)updateMyvCardTemp:(XMPPvCardTemp?*)vCardTemp; //獲取到一盒聯(lián)系人的名片信息的回調(diào) -?(void)xmppvCardTempModule:(XMPPvCardTempModule?*)vCardTempModule? ????????didReceivevCardTemp:(XMPPvCardTemp?*)vCardTemp? ?????????????????????forJID:(XMPPJID?*)jid |
3.2添加好友
| 1 2 3 4 5 6 7 8 9 | ????//name為用戶賬號 ????-?(void)XMPPAddFriendSubscribe:(NSString?*)name ????{ ????????//XMPPHOST?就是服務(wù)器名,??主機名 ????????XMPPJID?*jid?=?[XMPPJID?jidWithString:[NSString?stringWithFormat:@"%@@%@",name,XMPPHOST]]; ????????//[presence?addAttributeWithName:@"subscription"?stringValue:@"好友"]; ????????[xmppRoster?subscribePresenceToUser:jid]; ?????????? ????} |
3.3收到添加好友的請求
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ????-?(void)xmppRoster:(XMPPRoster?*)sender?didReceivePresenceSubscriptionRequest:(XMPPPresence?*)presence ????{ ????????//取得好友狀態(tài) ????????NSString?*presenceType?=?[NSString?stringWithFormat:@"%@",?[presence?type]];?//online/offline ????????//請求的用戶 ????????NSString?*presenceFromUser?=[NSString?stringWithFormat:@"%@",?[[presence?from]?user]]; ????????NSLog(@"presenceType:%@",presenceType); ?????????? ????????NSLog(@"presence2:%@??sender2:%@",presence,sender); ?????????? ????????XMPPJID?*jid?=?[XMPPJID?jidWithString:presenceFromUser]; ????????//接收添加好友請求 ????????[xmppRoster?acceptPresenceSubscriptionRequestFrom:jid?andAddToRoster:YES]; ?????????? ????} |
3.4刪除好友
| 1 2 3 4 5 6 7 | //刪除好友,name為好友賬號 -?(void)removeBuddy:(NSString?*)name?? {?? ????XMPPJID?*jid?=?[XMPPJID?jidWithString:[NSString?stringWithFormat:@"%@@%@",name,XMPPHOST]];?? ???????? ????[self?xmppRoster]?removeUser:jid];?? } |
4. 聊天室
初始化聊天室
| 1 2 3 4 5 6 | ????XMPPJID?*roomJID?=?[XMPPJID?jidWithString:ROOM_JID]; ?????? ????xmppRoom?=?[[XMPPRoom?alloc]?initWithRoomStorage:self?jid:roomJID]; ?????? ????[xmppRoom?activate:xmppStream]; ????[xmppRoom?addDelegate:self?delegateQueue:dispatch_get_main_queue()]; |
創(chuàng)建聊天室成功
| 1 2 3 4 | ????-?(void)xmppRoomDidCreate:(XMPPRoom?*)sender ????{ ????????DDLogInfo(@"%@:?%@",?THIS_FILE,?THIS_METHOD); ????} |
加入聊天室,使用昵稱
| 1 | ????[xmppRoom?joinRoomUsingNickname:@"quack"?history:nil]; |
獲取聊天室信息
| 1 2 3 4 5 6 7 | ????-?(void)xmppRoomDidJoin:(XMPPRoom?*)sender ????{ ????????[xmppRoom?fetchConfigurationForm]; ????????[xmppRoom?fetchBanList]; ????????[xmppRoom?fetchMembersList]; ????????[xmppRoom?fetchModeratorsList]; ????} |
如果房間存在,會調(diào)用委托
| 1 2 3 4 5 6 | ????//?收到禁止名單列表 ????-?(void)xmppRoom:(XMPPRoom?*)sender?didFetchBanList:(NSArray?*)items; ????//?收到好友名單列表 ????-?(void)xmppRoom:(XMPPRoom?*)sender?didFetchMembersList:(NSArray?*)items; ????//?收到主持人名單列表 ????-?(void)xmppRoom:(XMPPRoom?*)sender?didFetchModeratorsList:(NSArray?*)items; |
房間不存在,調(diào)用委托
| 1 2 3 | ????-?(void)xmppRoom:(XMPPRoom?*)sender?didNotFetchBanList:(XMPPIQ?*)iqError; ????-?(void)xmppRoom:(XMPPRoom?*)sender?didNotFetchMembersList:(XMPPIQ?*)iqError; ????-?(void)xmppRoom:(XMPPRoom?*)sender?didNotFetchModeratorsList:(XMPPIQ?*)iqError; |
離開房間
| 1 | [xmppRoom?deactivate:xmppStream]; |
XMPPRoomDelegate的其他代理方法:
離開聊天室
| 1 2 3 4 | ????-?(void)xmppRoomDidLeave:(XMPPRoom?*)sender ????{ ????????DDLogVerbose(@"%@:?%@",?THIS_FILE,?THIS_METHOD); ????} |
新人加入群聊
| 1 2 3 4 | ????-?(void)xmppRoom:(XMPPRoom?*)sender?occupantDidJoin:(XMPPJID?*)occupantJID ????{ ????????DDLogVerbose(@"%@:?%@",?THIS_FILE,?THIS_METHOD); ????} |
有人退出群聊
| 1 2 3 4 | ????-?(void)xmppRoom:(XMPPRoom?*)sender?occupantDidLeave:(XMPPJID?*)occupantJID ????{ ????????DDLogVerbose(@"%@:?%@",?THIS_FILE,?THIS_METHOD); ????} |
有人在群里發(fā)言
| 1 2 3 4 | ????-?(void)xmppRoom:(XMPPRoom?*)sender?didReceiveMessage:(XMPPMessage?*)message?fromOccupant:(XMPPJID?*)occupantJID ????{ ????????DDLogVerbose(@"%@:?%@",?THIS_FILE,?THIS_METHOD); ????} |
5. 消息回執(zhí)
這個是XEP-0184協(xié)議的內(nèi)容
協(xié)議內(nèi)容:
發(fā)送消息時附加回執(zhí)請求
代碼實現(xiàn)
| 1 2 3 4 5 6 7 | ????NSString?*siID?=?[XMPPStream?generateUUID]; ????//發(fā)送消息 ????XMPPMessage?*message?=?[XMPPMessage?messageWithType:@"chat"?to:jid?elementID:siID]; ????NSXMLElement?*receipt?=?[NSXMLElement?elementWithName:@"request"?xmlns:@"urn:xmpp:receipts"]; ????[message?addChild:receipt]; ????[message?addBody:@"測試"]; ????[self.xmppStream?sendElement:message]; |
收到回執(zhí)請求的消息,發(fā)送回執(zhí)
代碼實現(xiàn)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ????-?(void)xmppStream:(XMPPStream?*)sender?didReceiveMessage:(XMPPMessage?*)message ????{ ????????//回執(zhí)判斷 ????????NSXMLElement?*request?=?[message?elementForName:@"request"]; ????????if?(request) ????????{ ????????????if?([request.xmlns?isEqualToString:@"urn:xmpp:receipts"])//消息回執(zhí) ????????????{ ????????????????//組裝消息回執(zhí) ????????????????XMPPMessage?*msg?=?[XMPPMessage?messageWithType:[message?attributeStringValueForName:@"type"]?to:message.from?elementID:[message?attributeStringValueForName:@"id"]]; ????????????????NSXMLElement?*recieved?=?[NSXMLElement?elementWithName:@"received"?xmlns:@"urn:xmpp:receipts"]; ????????????????[msg?addChild:recieved]; ?????????????????? ????????????????//發(fā)送回執(zhí) ????????????????[self.xmppStream?sendElement:msg]; ????????????} ????????}else ????????{ ????????????NSXMLElement?*received?=?[message?elementForName:@"received"]; ????????????if?(received) ????????????{ ????????????????if?([received.xmlns?isEqualToString:@"urn:xmpp:receipts"])//消息回執(zhí) ????????????????{ ????????????????????//發(fā)送成功 ????????????????????NSLog(@"message?send?success!"); ????????????????}?? ????????????}?? ????????}?? ?????????? ????????//消息處理?? ????????//...?? ????} |
6. 添加AutoPing
為了監(jiān)聽服務(wù)器是否有效,增加心跳監(jiān)聽。用XEP-0199協(xié)議,在XMPPFrameWork框架下,封裝了?XMPPAutoPing 和?XMPPPing兩個類都可以使用,因為XMPPAutoPing已經(jīng)組合進了XMPPPing類,所以XMPPAutoPing使用起來更方便。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | //初始化并啟動ping -(void)autoPingProxyServer:(NSString*)strProxyServer { ????_xmppAutoPing?=?[[XMPPAutoPingalloc]?init]; ????[_xmppAutoPingactivate:_xmppStream]; ????[_xmppAutoPingaddDelegate:selfdelegateQueue:??dispatch_get_main_queue()]; ????_xmppAutoPing.respondsToQueries?=?YES; ????_xmppAutoPing.pingInterval=2;//ping?間隔時間 ????if?(nil?!=?strProxyServer) ????{ ???????_xmppAutoPing.targetJID?=?[XMPPJID?jidWithString:?strProxyServer?];//設(shè)置ping目標(biāo)服務(wù)器,如果為nil,則監(jiān)聽socketstream當(dāng)前連接上的那個服務(wù)器 ????} } //卸載監(jiān)聽 ?[_xmppAutoPing???deactivate]; ??[_xmppAutoPing???removeDelegate:self]; ???_xmppAutoPing?=?nil; //ping?XMPPAutoPingDelegate的委托方法: -?(void)xmppAutoPingDidSendPing:(XMPPAutoPing?*)sender { ????NSLog(@"-?(void)xmppAutoPingDidSendPing:(XMPPAutoPing?*)sender"); } -?(void)xmppAutoPingDidReceivePong:(XMPPAutoPing?*)sender { ????NSLog(@"-?(void)xmppAutoPingDidReceivePong:(XMPPAutoPing?*)sender"); } ??? -?(void)xmppAutoPingDidTimeout:(XMPPAutoPing?*)sender { ????NSLog(@"-?(void)xmppAutoPingDidTimeout:(XMPPAutoPing?*)sender"); } |
轉(zhuǎn)載于:https://www.cnblogs.com/fengmin/p/4973848.html
總結(jié)
以上是生活随笔為你收集整理的iOS 的 XMPPFramework 简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决PendingIntent传递参数为
- 下一篇: 青春谁不糊涂3