下载 XMPPFramework
框架
GitHub: XMPPFramework
导入依赖框架
CocoaLumberjack
: 日志框架
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扩展框架
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
并设置代理:
-(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);
}
}
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;
}
```
声明:
以上内容转自:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章