iOS即时通信之XMPP框架的使用及原理简介

2024-05-31 11:18

本文主要是介绍iOS即时通信之XMPP框架的使用及原理简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小公司可以考虑xmpp框架,xmpp内部封装好了异步的socket通信

XMPP是基于XML协议的分散型通讯网络,只要服务器的协议相同,服务器就可以和服务器通信;

XMPP的核心就是XML流传传输协议;

XMPP是C/S 架构;

XMPP中对应的模块会吧数据从服务器拿出来,然后放到本地数据库,我们开发只需要获取本地服务器的数据.




XMPP----------可扩展通讯和标示协议






==================

连接服务器,登录,注册

// 1. 初始化XMPPStream

-(void)setupXMPPStream;



// 2.连接到服务器

-(void)connectToHost;


// 3.连接到服务成功后,再发送密码授权

-(void)sendPwdToHost;



// 4.授权成功后,发送"在线"消息

-(void)sendOnlineToHost;

@end



@implementation WCXMPPTool



singleton_implementation(WCXMPPTool)




#pragma mark  -私有方法

#pragma mark 初始化XMPPStream

-(void)setupXMPPStream{

    

    _xmppStream = [[XMPPStreamalloc]init];

#warning 每一个模块添加后都要激活

    //添加电子名片模块

    _vCardStorage = [XMPPvCardCoreDataStoragesharedInstance];

    _vCard = [[XMPPvCardTempModulealloc]initWithvCardStorage:_vCardStorage];

    

    //激活

    [_vCard activate:_xmppStream];

    

    //添加头像模块

    _avatar = [[XMPPvCardAvatarModulealloc]initWithvCardTempModule:_vCard];

    [_avatar activate:_xmppStream];

    

    

    

    // 设置代理

    [_xmppStreamaddDelegate:selfdelegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)];

}


#pragma mark 连接到服务器

-(void)connectToHost{

    WCLog(@"开始连接到服务器");

    if (!_xmppStream) {

        [selfsetupXMPPStream];

    }

    

    

    // 设置登录用户JID

    //resource 标识用户登录的客户端 iphone android

    

    // 从单例获取用户名

    NSString *user = nil;

    if (self.isRegisterOperation) {

        user = [WCUserInfo sharedWCUserInfo].registerUser;

    }else{

        user = [WCUserInfo sharedWCUserInfo].user;

    }

    

    XMPPJID *myJID = [XMPPJIDjidWithUser:userdomain:@"teacher.local"resource:@"iphone" ];

    _xmppStream.myJID = myJID;

    

    // 设置服务器域名

    _xmppStream.hostName =@"teacher.local";//不仅可以是域名,还可是IP地址

    

    // 设置端口如果服务器端口是5222,可以省略

    _xmppStream.hostPort =5222;

    

    // 连接

    NSError *err = nil;

    if(![_xmppStreamconnectWithTimeout:XMPPStreamTimeoutNoneerror:&err]){

        WCLog(@"%@",err);

    }

    

}



#pragma mark 连接到服务成功后,再发送密码授权

-(void)sendPwdToHost{

    WCLog(@"再发送密码授权");

    NSError *err = nil;

    

    // 从单例里获取密码

    NSString *pwd = [WCUserInfosharedWCUserInfo].pwd;

    

    [_xmppStreamauthenticateWithPassword:pwderror:&err];

    

    if (err) {

        WCLog(@"%@",err);

    }

}


#pragma mark  授权成功后,发送"在线"消息

-(void)sendOnlineToHost{

    

    WCLog(@"发送在线消息");

    XMPPPresence *presence = [XMPPPresencepresence];

    WCLog(@"%@",presence);

    

    [_xmppStream sendElement:presence];

    

    

}

#pragma mark -XMPPStream的代理

#pragma mark 与主机连接成功

-(void)xmppStreamDidConnect:(XMPPStream *)sender{

    WCLog(@"与主机连接成功");

    

    if (self.isRegisterOperation) {//注册操作,发送注册的密码

        NSString *pwd = [WCUserInfosharedWCUserInfo].registerPwd;

        [_xmppStreamregisterWithPassword:pwderror:nil];

    }else{//登录操作

        // 主机连接成功后,发送密码进行授权

        [selfsendPwdToHost];

    }

    

}

#pragma mark  与主机断开连接

-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{

    // 如果有错误,代表连接失败

    

    // 如果没有错误,表示正常的断开连接(人为断开连接)

    

    

    if(error && _resultBlock){

        _resultBlock(XMPPResultTypeNetErr);

    }

    WCLog(@"与主机断开连接 %@",error);

    

}



#pragma mark 授权成功

-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{

    WCLog(@"授权成功");

    

    [selfsendOnlineToHost];

    

    // 回调控制器登录成功

    if(_resultBlock){

        _resultBlock(XMPPResultTypeLoginSuccess);

    }

    

    

}



#pragma mark 授权失败

-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{

    WCLog(@"授权失败 %@",error);

    

    // 判断block有无值,回调给登录控制器

    if (_resultBlock) {

        _resultBlock(XMPPResultTypeLoginFailure);

    }

}


#pragma mark 注册成功

-(void)xmppStreamDidRegister:(XMPPStream *)sender{

    WCLog(@"注册成功");

    if(_resultBlock){

        _resultBlock(XMPPResultTypeRegisterSuccess);

    }

    

}


#pragma mark 注册失败

-(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{

    

    WCLog(@"注册失败 %@",error);

    if(_resultBlock){

        _resultBlock(XMPPResultTypeRegisterFailure);

    }

    

}


#pragma mark -公共方法

-(void)xmppUserlogout{

    // 1." 发送 "离线"消息"

    XMPPPresence *offline = [XMPPPresencepresenceWithType:@"unavailable"];

    [_xmppStream sendElement:offline];

    

    // 2. 与服务器断开连接

    [_xmppStream disconnect];

    

    // 3. 回到登录界面

//    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Login" bundle:nil];

//    

//    self.window.rootViewController = storyboard.instantiateInitialViewController;

    [UIStoryboardshowInitialVCWithName:@"Login"];

    

    

    //4.更新用户的登录状态

    [WCUserInfosharedWCUserInfo].loginStatus =NO;

    [[WCUserInfosharedWCUserInfo]saveUserInfoToSanbox];

    

}


-(void)xmppUserLogin:(XMPPResultBlock)resultBlock{

    

    // 先把block存起来

    _resultBlock = resultBlock;

    

    //    Domain=XMPPStreamErrorDomain Code=1 "Attempting to connect while already connected or connecting." UserInfo=0x7fd86bf06700 {NSLocalizedDescription=Attempting to connect while already connected or connecting.}

    // 如果以前连接过服务,要断开

    [_xmppStream disconnect];

    

    // 连接主机成功后发送登录密码

    [selfconnectToHost];

}



-(void)xmppUserRegister:(XMPPResultBlock)resultBlock{

    // 先把block存起来

    _resultBlock = resultBlock;

    

    // 如果以前连接过服务,要断开

    [_xmppStream disconnect];

    

    // 连接主机成功后发送注册密码

    [selfconnectToHost];

}


======================

xmpp的一般开发步骤:

1.导入指定模块的头文件

2.创建导入的指定模块的对象

3.设置参数

4.设置代理 (需要代理才设置)

5.激活模块

=================================

0054电子明片(个人资料)的设置:

个人资料功能模块------XMPPVcardTempModule.h

个人资料的存储集合----------XMPPvCardTemp  *myvCardTemp,是XMPPVcardTempModule的一个属性;

个人资料的数据库存储-------XMPPvCardCoreDataStorage.h

 个人资料数据库对象-----------XMPPvCardTempCoreDataStorageObject.h

头像功能模块-----XMPPvCardAVatarModule.h

头像数据存储对象-----XMPPvCardAvatarCoreDataStorageObject.h

@property (nonatomicstrong)XMPPvCardCoreDataStorage *vCardStorage;//电子名片的数据存储

    

@property (nonatomicstrong)XMPPvCardAvatarModule *avatar;//头像模块

 

@property (nonatomicstrong)XMPPvCardTempModule *vCard;//电子名片模块



_xmppStream = [[XMPPStreamalloc]init];

#warning 每一个模块添加后都要激活

    //添加电子名片模块

    _vCardStorage = [XMPPvCardCoreDataStoragesharedInstance];

    _vCard = [[XMPPvCardTempModulealloc]initWithvCardStorage:_vCardStorage];

    

    //激活

    [_vCard activate:_xmppStream];

    

    //添加头像模块

    _avatar = [[XMPPvCardAvatarModulealloc]initWithvCardTempModule:_vCard];

    [_avatar activate:_xmppStream];



    

    //xmpp提供了一个方法,直接获取个人信息(电子面片的功能模块有一个个人信息的集合属性:XMPPvCardTemp *myvCardTemp)

    

   XMPPvCardTemp *myVCard =vCard.myvCardTemp;

    

    // 设置头像

    if(myVCard.photo){

        self.headerView.image = [UIImageimageWithData:myVCard.photo];

    }

    

    // 设置昵称

    self.nickNameLabel.text = myVCard.nickname;

    

    // 设置微信号[用户名]

    

    NSString *user = [WCUserInfosharedWCUserInfo].user;

    self.weixinNumLabel.text = [NSStringstringWithFormat:@"微信号:%@",user];


//更新这个方法内部会实现数据上传到服务器,无需程序自己操作

    [vCardupdateMyvCardTemp:myvCard];



================
心跳检测模块-----XMPPAutoPing.h
自动重连模块--------XMPPReconnect.h;


@property (nonatomicstrong)

XMPPReconnect *reconnect;// 自动连接模块


    //添加自动连接模块

    _reconnect = [[XMPPReconnectalloc]init];

    [_reconnect activate:_xmppStream];


===================================
花名册模块--------XMPPRoster.h
好友实体数据库存储--------XMPPRosterCoreDataStorage.h
好友实体对象-----XMPPUserCoreDataStorageObject.h

@property (nonatomicstrong)XMPPRosterCoreDataStorage *rosterStorage;//花名册数据存储

@property (nonatomicstrong)XMPPRoster *roster;//花名册模块



    //添加花名册模块【获取好友列表】

    _rosterStorage = [[XMPPRosterCoreDataStoragealloc]init];

    _roster = [[XMPPRosteralloc]initWithRosterStorage:_rosterStorage];

    [_roster activate:_xmppStream];



//方法一:    通过上下文  获取好友数据

    // 1.获取对象管理上下文【关联到数据库XMPPRoster.sqlite

    NSManagedObjectContext *context =rosterStorage.mainThreadManagedObjectContext;

    

    

    // 2.FetchRequest【查哪张表】通过实体(相当于表)查找

    NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"];

    

    // 3.设置过滤和排序

    // 过滤当前登录用户的好友

    NSString *jid = [WCUserInfosharedWCUserInfo].jid;

    NSPredicate *pre = [NSPredicatepredicateWithFormat:@"streamBareJidStr = %@",jid];

    request.predicate = pre;

    

    //排序

    NSSortDescriptor *sort = [NSSortDescriptorsortDescriptorWithKey:@"displayName"ascending:YES];

    request.sortDescriptors = @[sort];

    

    // 4.执行请求获取数据集合(集合里面的元素都是XMPPUserCoreDataStorageObject类型)

    self.friends = [contextexecuteFetchRequest:requesterror:nil];

    NSLog(@"%@",self.friends);


方法二:通过查询控制器查询获取

<NSFetchedResultsControllerDelegate>协议

{

    NSFetchedResultsController *_resultsContrl;

}

// 1.上下文【关联到数据库XMPPRoster.sqlite

    NSManagedObjectContext *context =rosterStorage.mainThreadManagedObjectContext;

    

    

    // 2.FetchRequest【查哪张表】

    NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"];

    

    // 3.设置过滤和排序

    // 过滤当前登录用户的好友

    NSString *jid = [WCUserInfosharedWCUserInfo].jid;

    NSPredicate *pre = [NSPredicatepredicateWithFormat:@"streamBareJidStr = %@",jid];

    request.predicate = pre;

    

    //排序

    NSSortDescriptor *sort = [NSSortDescriptorsortDescriptorWithKey:@"displayName"ascending:YES];

    request.sortDescriptors = @[sort];

    

    // 4.执行请求获取数据,获取好友集合(集合里面的元素都是XMPPUserCoreDataStorageObject类型)

    _resultsContrl = [[NSFetchedResultsControlleralloc]initWithFetchRequest:requestmanagedObjectContext:contextsectionNameKeyPath:nilcacheName:nil];

    

    _resultsContrl.delegate =self;

    

    NSError *err = nil;

    [_resultsContrlperformFetch:&err];



#pragma mark 当数据的内容发生改变后,会调用这个方法

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller{

    WCLog(@"数据发生改变");

    //刷新表格

    [self.tableViewreloadData];

}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return_resultsContrl.fetchedObjects.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    staticNSString *ID =@"ContactCell";

    UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];



    // 获取对应好友

    //XMPPUserCoreDataStorageObject *friend =self.friends[indexPath.row];

    XMPPUserCoreDataStorageObject *friend = _resultsContrl.fetchedObjects[indexPath.row];//通过传控制器获取的好友实体对象

    //    sectionNum

    //    “0”- 在线

    //    “1”- 离开

    //    “2”- 离线

    switch ([friend.sectionNumintValue]) {//好友对象的状态

        case 0:

            cell.detailTextLabel.text =@"在线";

            break;

        case 1:

            cell.detailTextLabel.text =@"离开";

            break;

        case 2:

            cell.detailTextLabel.text =@"离线";

            break;

        default:

            break;

    }

    cell.textLabel.text = friend.jidStr;//jid的类型是xxx@aaa.com

    

    return cell;

}


openfire服务器删除好友后,下面这个方法会接收到删除好友的消息后,花名册模块就会吧数据库roster.sqlite相应的好友删除

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller,

// 删除好友,  实现这个方法,cell往左滑就会有个delete

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

    if (editingStyle ==UITableViewCellEditingStyleDelete) {

        WCLog(@"删除好友");

        XMPPUserCoreDataStorageObject *friend =_resultsContrl.fetchedObjects[indexPath.row];

        

        XMPPJID *freindJid = friend.jid;

        [[WCXMPPTool sharedWCXMPPTool].roster removeUser:freindJid];

    }

}


=============================
在textfield代理方法中

-(BOOL)textFieldShouldReturn:(UITextField *)textField{

    // 添加好友

    

    // 1.获取好友账号

    NSString *user = textField.text;

    WCLog(@"%@",user);

    

    // 判断这个账号是否为手机号码

    if(![textField isTelphoneNum]){

        //提示

        [self showAlert:@"请输入正确的手机号码"];

        return YES;

    }

    

    

    //判断是否添加自己

    if([user isEqualToString:[WCUserInfosharedWCUserInfo].user]){

        

        [self showAlert:@"不能添加自己为好友"];

        return YES;

    }

    NSString *jidStr = [NSStringstringWithFormat:@"%@@%@",user,domain];

    XMPPJID *friendJid = [XMPPJIDjidWithString:jidStr];

    

    

    //判断好友是否已经存在

    if([[WCXMPPToolsharedWCXMPPTool].rosterStorageuserExistsWithJID:friendJidxmppStream:[WCXMPPToolsharedWCXMPPTool].xmppStream]){

        [self showAlert:@"当前好友已经存在"];

        return YES;

    }

    

    

    // 2.发送好友添加的请求

    // 添加好友,xmpp有个叫订阅

  

    [[WCXMPPToolsharedWCXMPPTool].rostersubscribePresenceToUser:friendJid];

    

    return YES;

}


-(void)showAlert:(NSString *)msg{

    

    UIAlertView *alert = [[UIAlertViewalloc]initWithTitle:@"温馨提示"message:msgdelegate:nilcancelButtonTitle:@"谢谢"otherButtonTitles:nil,nil];

    [alert show];

}

@end


====================
聊天消息模块,显示消息,发送消息,发送图片

// 消息模块

消息功能模块-------"XMPPMessageArchiving.h"

消息数据存储------"XMPPMessageArchivingCoreDataStorage.h"

消息实体对象-------XMPPMessageArchiving_Message_CoreDataObject.h

最近联系人实体对象------XMPPMessageArchiving_Contact_CoreDataObject.h


#pragma mark 加载XMPPMessageArchiving数据库的数据显示在表格

-(void)loadMsgs{


    // 上下文

    NSManagedObjectContext *context = [WCXMPPToolsharedWCXMPPTool].msgStorage.mainThreadManagedObjectContext;

    // 请求对象

    NSFetchRequest *request = [NSFetchRequestfetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"];

    

    

    // 过滤、排序

    // 1.当前登录用户的JID的消息

    // 2.好友的Jid的消息

    NSPredicate *pre = [NSPredicatepredicateWithFormat:@"streamBareJidStr = %@ AND bareJidStr = %@",[WCUserInfosharedWCUserInfo].jid,self.friendJid.bare];

    NSLog(@"%@",pre);

    request.predicate = pre;

    

    // 时间升序

    NSSortDescriptor *timeSort = [NSSortDescriptorsortDescriptorWithKey:@"timestamp"ascending:YES];

    request.sortDescriptors = @[timeSort];

   

    // 查询

    _resultsContr = [[NSFetchedResultsControlleralloc]initWithFetchRequest:requestmanagedObjectContext:contextsectionNameKeyPath:nilcacheName:nil];

    

    NSError *err = nil;

    // 代理

    _resultsContr.delegate =self;

    

    [_resultsContr performFetch:&err];

    

    NSLog(@"%@",_resultsContr.fetchedObjects);

    if (err) {

        WCLog(@"%@",err);

    }

}


#pragma mark -表格的数据源

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return_resultsContr.fetchedObjects.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *ID =@"ChatCell";

    UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];

    if (!cell) {

        cell = [[UITableViewCellalloc]initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:ID];

    }

    

    // 获取聊天消息对象

    XMPPMessageArchiving_Message_CoreDataObject *msg = _resultsContr.fetchedObjects[indexPath.row];

    

    

    // 判断是图片还是纯文本

    NSString *chatType = [msg.messageattributeStringValueForName:@"bodyType"];

    if ([chatType isEqualToString:@"image"]) {

        //下图片显示

        [cell.imageViewsd_setImageWithURL:[NSURLURLWithString:msg.body]placeholderImage:[UIImageimageNamed:@"DefaultProfileHead_qq"]];

        cell.textLabel.text =nil;

    }else if([chatTypeisEqualToString:@"text"]){

    

        //显示消息

        if ([msg.outgoingboolValue]) {//自己发

            cell.textLabel.text = msg.body;

        }else{//别人发的

            cell.textLabel.text = msg.body;

        }

        

        cell.imageView.image =nil;

    }

    

    

//    //显示消息

//    if ([msg.outgoing boolValue]) {//自己发

//        cell.textLabel.text = [NSString stringWithFormat:@"Me: %@",msg.body];

//    }else{//别人发的

//        cell.textLabel.text = [NSString stringWithFormat:@"Other: %@",msg.body];

//    }

    

    

    

    return cell;

}



#pragma mark ResultController的代理

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller{

    // 刷新数据

    [self.tableViewreloadData];

    [selfscrollToTableBottom];

}


#pragma mark TextView的代理

-(void)textViewDidChange:(UITextView *)textView{

    //获取ContentSize

    CGFloat contentH = textView.contentSize.height;

    NSLog(@"textViewcontent的高度 %f",contentH);

    

    // 大于33,超过一行的高度/小于68高度是在三行内

    if (contentH > 33 && contentH < 68 ) {

        self.inputViewHeightConstraint.constant = contentH +18;

    }

    

    NSString *text = textView.text;

    

    

    // 换行就等于点击了的send

    if ([text rangeOfString:@"\n"].length !=0) {

        NSLog(@"发送数据 %@",text);

        

        // 去除换行字符

        text = [text stringByTrimmingCharactersInSet:[NSCharacterSetwhitespaceAndNewlineCharacterSet]];

        

        [selfsendMsgWithText:textbodyType:@"text"];

        //清空数据

        textView.text = nil;

        

        // 发送完消息 inputView的高度改回来

        self.inputViewHeightConstraint.constant =50;

        

    }else{

        NSLog(@"%@",textView.text);


    }

}



#pragma mark 发送聊天消息

-(void)sendMsgWithText:(NSString *)text bodyType:(NSString *)bodyType{

    

    XMPPMessage *msg = [XMPPMessagemessageWithType:@"chat"to:self.friendJid];

    

    //text 纯文本

    //image 图片

    [msg addAttributeWithName:@"bodyType"stringValue:bodyType];

   

    // 设置内容

    [msg addBody:text];

     NSLog(@"%@",msg);

    [[WCXMPPToolsharedWCXMPPTool].xmppStreamsendElement:msg];

}


#pragma mark 滚动到底部

-(void)scrollToTableBottom{

    NSInteger lastRow =_resultsContr.fetchedObjects.count -1;

    

    if (lastRow < 0) {

        //行数如果小于0,不能滚动

        return;

    }

    NSIndexPath *lastPath = [NSIndexPathindexPathForRow:lastRowinSection:0];

    

    [self.tableViewscrollToRowAtIndexPath:lastPathatScrollPosition:UITableViewScrollPositionBottomanimated:YES];

}



#pragma mark 选择图片

-(void)addBtnClick{

    UIImagePickerController *imagePicker = [[UIImagePickerControlleralloc]init];

    imagePicker.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;

    imagePicker.delegate = self;

    [selfpresentViewController:imagePickeranimated:YEScompletion:nil];


}


#pragma mark 选取后图片的回调

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

    NSLog(@"%@",info);

    // 隐藏图片选择器的窗口

    [selfdismissViewControllerAnimated:YEScompletion:nil];

    

    // 获取图片

    UIImage *image = info[UIImagePickerControllerOriginalImage];

    

    // 把图片发送到文件服务器

    //http post put

    /**

     * put实现文件上传没post那烦锁,而且比POST

     * put的文件上传路径就是下载路径

     

     *文件上传路径http://localhost:8080/imfileserver/Upload/Image/ + "图片名【程序员自已定义】"

     */

    

    // 1.取文件名用户名 +时间(201412111537)年月日时分秒

    NSString *user = [WCUserInfosharedWCUserInfo].user;


    NSDateFormatter *dataFormatter = [[NSDateFormatteralloc]init];

    dataFormatter.dateFormat = @"yyyyMMddHHmmss";

    NSString *timeStr = [dataFormatter stringFromDate:[NSDate date]];

    

    // 针对我的服务,文件名不用加后缀

    NSString *fileName = [user stringByAppendingString:timeStr];

    

    // 2.拼接上传路径

    NSString *uploadUrl = [@"http://localhost:8080/imfileserver/Upload/Image/"stringByAppendingString:fileName];

    

    

    // 3.使用HTTP put上传

#warning 图片上传请使用jpg格式因为我写的服务器只接接收jpg

    [self.httpTooluploadData:UIImageJPEGRepresentation(image,0.75)url:[NSURLURLWithString:uploadUrl]progressBlock:nilcompletion:^(NSError *error) {

       

        if (!error) {

            NSLog(@"上传成功");

            [self sendMsgWithText:uploadUrl bodyType:@"image"];

        }

    }];

    

    

    // 图片发送成功,把图片的URLOpenfire的服务

}


======================

-(void)dealloc{

    [selfteardownXmpp];

}



#pragma mark 释放xmppStream相关的资源

-(void)teardownXmpp{

    

    // 移除代理

    [_xmppStreamremoveDelegate:self];

    

    // 停止模块

    [_reconnect deactivate];

    [_vCarddeactivate];

    [_avatardeactivate];

    [_rosterdeactivate];

    [_msgArchivingdeactivate];

    

    // 断开连接

    [_xmppStream disconnect];

    

    // 清空资源

    _reconnect = nil;

    _vCard = nil;

    _vCardStorage =nil;

    _avatar = nil;

    _roster = nil;

    _rosterStorage =nil;

    _msgArchiving =nil;

    _msgStorage = nil;

    _xmppStream = nil;


}





#pragma mark 接收到好友消息时调用的代理方法

-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{

    WCLog(@"%@",message);

    

    //如果当前程序不在前台,发出一个本地通知

    if([UIApplicationsharedApplication].applicationState !=UIApplicationStateActive){

        WCLog(@"在后台");

        

        //本地通知

        UILocalNotification *localNoti = [[UILocalNotificationalloc] init];

        

        // 设置内容

        localNoti.alertBody = [NSStringstringWithFormat:@"%@\n%@",message.fromStr,message.body];

        

        // 设置通知执行时间

        localNoti.fireDate = [NSDatedate];

        

        //声音

        localNoti.soundName = @"default";

        

        //执行

        [[UIApplicationsharedApplication] scheduleLocalNotification:localNoti];

        

        //{"aps":{'alert':"zhangsan\n have dinner":'sound':'default',badge:'12'}}

    }

}



//好友在线状态改变的代理方法

-(void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence{

    //XMPPPresence 在线 离线

    

    //presence.from 消息是谁发送过来

}




这篇关于iOS即时通信之XMPP框架的使用及原理简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1017794

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是

通信系统网络架构_2.广域网网络架构

1.概述          通俗来讲,广域网是将分布于相比局域网络更广区域的计算机设备联接起来的网络。广域网由通信子网于资源子网组成。通信子网可以利用公用分组交换网、卫星通信网和无线分组交换网构建,将分布在不同地区的局域网或计算机系统互连起来,实现资源子网的共享。 2.网络组成          广域网属于多级网络,通常由骨干网、分布网、接入网组成。在网络规模较小时,可仅由骨干网和接入网组成

iOS HTTPS证书不受信任解决办法

之前开发App的时候服务端使用的是自签名的证书,导致iOS开发过程中调用HTTPS接口时,证书不被信任 - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAu

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers