下載 XMPPFramework
框架android
GitHub: XMPPFrameworkgit
導入依賴框架github
CocoaLumberjack
: 日誌框架sql
CocoaAsyncSocket
: 底層網絡框架
須要添加 CFNetwork
& Security
框架依賴(XCode 6+ 無需導入)數據庫
KissXML
: XML解析框架
須要添加libxml2.dylib
框架依賴
須要指定以下編譯選項:
Other Linker Flags = -lxml2
Header Search Paths = /usr/include/libxml2服務器
libidn
網絡
導入一下文件夾框架
Authentication
Categories
Core
Utilities
libresolv.dylib
導入XMPP擴展框架dom
Extensions
文件夾Sample_XMPPFramework.h
並改名爲:XMPPFramework.h
Add New File
-> Other
-> PCH文件
#import<UIKit/UIKit.h>
到PCH文件中Build Settings
-> Precompile prefix Header
選擇Yes
Build Settings
-> Prefix Header
設置PCH文件名:「項目名/「PCH文件名」
1. 實例化XMPPStream並設置代理,同時添加代理到工做隊列 2. 使用JID鏈接至服務器,默認端口爲5222,JID字符串中須要包含服務器的域名 3. 在完成鏈接的代理方法中驗證用戶密碼,鏈接完成後XMPPStream的isConnect屬性爲YES 4. 在驗證代理方法中判斷用戶是否登陸成功 5. 上線或者下線成功後,向服務器發送Presence數據,以更新用戶在服務器的狀態
初始化 XMPPStream
並設置代理:iphone
-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; // 設置代理 [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; }
鏈接到服務器
-(void)connectToHost{ NSLog(@"開始鏈接到服務器"); if (!_xmppStream) { [self setupXMPPStream]; } // 設置登陸用戶JID //resource 標識用戶登陸的客戶端 iphone android XMPPJID *myJID = [XMPPJID jidWithUser:@"aaa" domain:@"bourne-mbp.local" resource:@"iphone" ]; _xmppStream.myJID = myJID; // 設置服務器域名 _xmppStream.hostName = @"bourne-mbp.local";//不只能夠是域名,還但是IP地址 // 設置端口 若是服務器端口是5222,能夠省略 _xmppStream.hostPort = 5222; // 鏈接 NSError *err = nil; if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){ NSLog(@"%@",err); } }
鏈接成功後發送密碼驗證
-(void)sendPwdToHost{ NSLog(@"再發送密碼受權"); NSError *err = nil; [_xmppStream authenticateWithPassword:@"123456" error:&err]; if (err) { NSLog(@"%@",err); } }
受權成功後,發送 在線
消息
#pragma mark 受權成功後,發送"在線" 消息
-(void)sendOnlineToHost{ NSLog(@"發送 在線 消息"); XMPPPresence *presence = [XMPPPresence presence]; NSLog(@"%@",presence); [_xmppStream sendElement:presence]; }
#pragma mark 與主機鏈接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{ NSLog(@"與主機鏈接成功"); // 主機鏈接成功後,發送密碼進行受權 [self sendPwdToHost]; }
#pragma mark 與主機斷開鏈接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{
// 若是有錯誤,表明鏈接失敗 NSLog(@"與主機斷開鏈接 %@",error);
}
#pragma mark 受權成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
NSLog(@"受權成功"); [self sendOnlineToHost];
}
#pragma mark 受權失敗
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
NSLog(@"受權失敗 %@",error);
}
離線
信息-(void)logout{ // 1." 發送 `離線` 消息" XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"]; [_xmppStream sendElement:offline]; // 2. 與服務器斷開鏈接 [_xmppStream disconnect]; }
與登陸同樣,首先發送賬號創建鏈接
鏈接成功後,發送註冊的密碼
註冊成功後,框架會通知代理
- (void)xmppStreamDidRegister:(XMPPStream *)sender { NSLog(@"註冊成功"); if (_resultBlock) { _resultBlock(BWXMPPLoginResultSuccessed); } } - (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error { if (_resultBlock) { _resultBlock(BWXMPPLoginResultFailure); } }
XMPP是面向模塊的,每個大的動能都屬於某一個模塊,須要使用時,就在頭文件中將其暴露出來(本來是被註釋了的)。
工做原理:
添加用戶信息模塊以後,
XMPPFramework框架
會自動從服務器獲取用戶信息,並使用CoreData
保存到本地的數據庫中,使用XMPPvCardTempModule
能夠訪問數據
在XMPPFramework.h
中將如下的頭文件前面的註釋去掉:
// 電子名片模塊 #import "XMPPvCardTempModule.h" #import "XMPPvCardCoreDataStorage.h" // 頭像模塊 #import "XMPPvCardAvatarModule.h"
初始化模塊
//添加電子名片模塊 _vCardStorage = [XMPPvCardCoreDataStorage sharedInstance]; _vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage]; //激活 [_vCard activate:_xmppStream]; //添加頭像模塊 _avatar = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_vCard]; [_avatar activate:_xmppStream];
應用
//xmpp提供了一個方法,直接獲取我的信息 XMPPvCardTemp *myVCard =[WCXMPPTool sharedWCXMPPTool].vCard.myvCardTemp; // 設置頭像 if(myVCard.photo){ self.haedView.image = [UIImage imageWithData:myVCard.photo]; } // 設置暱稱 self.nicknameLabel.text = myVCard.nickname;
與用戶信息模塊類似,添加相應的好友花名冊模塊便可。
頭文件
// 花名冊模塊 #import "XMPPRoster.h" #import "XMPPRosterCoreDataStorage.h"
初始化
// 添加花名冊模塊【獲取好友列表】 _rosterStorage = [[XMPPRosterCoreDataStorage alloc] init]; _roster = [[XMPPRoster alloc] initWithRosterStorage:_rosterStorage]; [_roster activate:_xmppStream];
應用
//使用CoreData獲取數據 // 1.上下文【關聯到數據庫XMPPRoster.sqlite】 NSManagedObjectContext *context = [WCXMPPTool sharedWCXMPPTool].rosterStorage.mainThreadManagedObjectContext; // 2.FetchRequest【查哪張表】 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"]; // 3.設置過濾和排序 // 過濾當前登陸用戶的好友 NSString *jid = [WCUserInfo sharedWCUserInfo].jid; NSPredicate *pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@",jid]; request.predicate = pre; //排序 NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"displayName" ascending:YES]; request.sortDescriptors = @[sort]; // 4.執行請求獲取數據 _resultsContrl = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; _resultsContrl.delegate = self; NSError *err = nil; [_resultsContrl performFetch:&err]; if (err) { WCLog(@"%@",err); }
NSFetchedResultsController
並設置代理,若是數據庫的內容發生了變化,這個類會自動通知代理,就能夠設置界面的數據,作到實時更新。頭文件
XMPPFramework.h
文件中,須要本身添加// 消息模塊 #import "XMPPMessageArchiving.h" #import "XMPPMessageArchivingCoreDataStorage.h"
初始化
// 添加聊天模塊 _msgStorage = [[XMPPMessageArchivingCoreDataStorage alloc] init]; _msgArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:_msgStorage]; [_msgArchiving activate:_xmppStream];
應用
// 上下文 NSManagedObjectContext *context = [WCXMPPTool sharedWCXMPPTool].msgStorage.mainThreadManagedObjectContext; // 請求對象 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"]; // 過濾、排序 // 1.當前登陸用戶的JID的消息 // 2.好友的Jid的消息 NSPredicate *pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@ AND bareJidStr = %@",[WCUserInfo sharedWCUserInfo].jid,self.friendJid.bare]; NSLog(@"%@",pre); request.predicate = pre; // 時間升序 NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:YES]; request.sortDescriptors = @[timeSort]; // 查詢 _resultsContr = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; NSError *err = nil; // 代理 _resultsContr.delegate = self; [_resultsContr performFetch:&err]; NSLog(@"%@",_resultsContr.fetchedObjects); if (err) { WCLog(@"%@",err); }
原理分析
base64
將文件轉化爲字符串,而後再經過XMPPFramework
傳輸。XMPPFramework
轉輸給好友,好友收到後再自行下載文件。難點解析
XMPPFramework
的``數據體添加一個信息類型字段。XMPPMessage *msg = [XMPPMessage messageWithType:@"chat" to:self.friendJid]; //text 純文本 //image 圖片 [msg addAttributeWithName:@"bodyType" stringValue:bodyType]; // 設置內容 [msg addBody:text]; NSLog(@"%@",msg); [[WCXMPPTool sharedWCXMPPTool].xmppStream sendElement:msg];
```objc
XMPPMessageArchiving_Message_CoreDataObject *msg = _resultsContr.fetchedObjects[indexPath.row]; // 判斷是圖片仍是純文本 NSString *chatType = [msg.message attributeStringValueForName:@"bodyType"]; if ([chatType isEqualToString:@"image"]) { //下圖片顯示 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:msg.body] placeholderImage:[UIImage imageNamed:@"DefaultProfileHead_qq"]]; cell.textLabel.text = nil; } else if ([chatType isEqualToString:@"text"]){ //顯示消息 if ([msg.outgoing boolValue]) {//本身發 cell.textLabel.text = msg.body; }else{//別人發的 cell.textLabel.text = msg.body; } cell.imageView.image = nil; }
```
聲明:
以上內容轉自:
http://www.jianshu.com/p/c7bbbad90639#