iOS XMPP——消息列表与发消息
2015-11-12 本文已影响1655人
iOS_成才录
- 1、XMPPFrame.h头开启下面代码
// 添加消息模块
#import "XMPPMessageArchiving.h"
#import "XMPPMessageArchivingCoreDataStorage.h"
- 2、在AppDelegate.h头文件中,加入以下属性
// 消息模块
@property (nonatomic, strong,readonly) XMPPMessageArchiving *msgArching;
// 消息数据存储
@property (nonatomic, strong,readonly)XMPPMessageArchivingCoreDataStorage *msgArchingStorage;
消息列表展示
- 需求:创建控制器,将消息列表 展示数据 到 tableView上
- 1、 控制器中导入头文件 #import "JPAppDelegate.h"
- 2、展示消息列表数据
#import "JPChatViewController.h"
#import "JPAppDelegate.h"
#import "UIImageView+WebCache.h"
@interface JPChatViewController ()<NSFetchedResultsControllerDelegate, UIImagePickerControllerDelegate>{
NSFetchedResultsController *_resultContr;//数据库查询结果控制器
}
@end
@implementation JPChatViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//数据绑定到tableview
[self dataBind];
}
- (void)dataBind{
//1.上下文
NSManagedObjectContext *context = xmppDelegate.msgArchingStorage.mainThreadManagedObjectContext;
//2.查询请求(查询哪张表)
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"];
//3.设置排序(时间升序)
NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:YES];
request.sortDescriptors = @[timeSort];
//4.过滤条件(当前登录用户jid , 好友jid)
XMPPJID *myJid = xmppDelegate.xmppStream.myJID;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bareJidStr = %@ AND streamBareJidStr = %@",self.friendJid.bare,myJid.bare];
request.predicate = predicate;
//[context executeFetchRequest:request error:nil];
_resultContr = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
//设置代理
_resultContr.delegate = self;
//执行请求
NSError *error = nil;
[_resultContr performFetch:&error];
if (error) {
JPLogError(@"%@",error);
}
}
#pragma mark -table的数据源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _resultContr.fetchedObjects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ID = @"ChatCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//消息模型
XMPPMessageArchiving_Message_CoreDataObject *chatMessage = _resultContr.fetchedObjects[indexPath.row];
// //自己发送的消息
// if ([chatMessage.outgoing boolValue]) {
// //设置消息内容
// cell.textLabel.text =[NSString stringWithFormat:@"me:%@",chatMessage.body];
// }else{//好友发送的消息
//
// cell.textLabel.text =[NSString stringWithFormat:@"other:%@",chatMessage.body];
// }
//判断是否有图片
if ([chatMessage.body rangeOfString:kImageTag].location != NSNotFound) {
NSString *imgUrl = [chatMessage.body substringFromIndex:kImageTag.length];
NSLog(@"有图片 %@",imgUrl);
//显示图片
[cell.imageView setImageWithURL:[NSURL URLWithString:imgUrl]placeholderImage:[UIImage imageNamed:@"DefaultProfileHead"]];
//消除文字
cell.textLabel.text = nil;
}else{
NSLog(@"无图片");
//设置消息内容
cell.textLabel.text =chatMessage.body;
//消除图片
cell.imageView.image = nil;
}
return cell;
}
@end
发消息
- [xmppDelegate.xmppStream sendElement:message];
//发送消息
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
NSString *text = textField.text;
// //添加图片标识
// NSString *imageText = [NSString stringWithFormat:@"img:%@",text];
// JPLogInfo(@"%@",imageText);
//
// //音频标识
// NSString *soundText = [NSString stringWithFormat:@"sound:%@",text];
// JPLogInfo(@"%@",imageText);
//封装消息对象
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
[message addBody:text];
//所有跟根据通信的话,用XMPPStream
//发送消息
[xmppDelegate.xmppStream sendElement:message];
//消除文字
textField.text = nil;
return YES;
}
发送图片:
- 打开相册 选择图片
UIImagePickerController *imagePicker =[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:imagePicker animated:YES completion:nil];
- 选择到图片从相册中,往文件服务器上传图片,然后把图片完整链接发给通信好友
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSLog(@"%@",info);
UIImage *image = info[UIImagePickerControllerOriginalImage];
//销毁图片选择控制器
[self dismissViewControllerAnimated:YES completion:nil];
//往文件服务器上传图片
//http://localhost:8080/imfileserver/Upload/Image/00001
//1.给图片全名
//username + time = zhangsan20140821140710
//username + time = wangwu20140821140710
NSString *username = xmppDelegate.xmppStream.myJID.user;
//2.获取时间字符串
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// formatter.dateFormat = @"yyyyMMddHHmmss";
// NSDate *nowDate = [NSDate date];
// NSString *time = [formatter stringFromDate:nowDate];
// 上面方式太麻烦了,使用我们自己自定义的分类来简化时间获取
NSString *time = [NSDate nowDateFormat:JPDateFormatyyyyMMddHHmmss];
NSString *imageName = [NSString stringWithFormat:@"%@%@",username,time];
JPLogInfo(@"imageName %@",imageName);
/**
* 基准路径 http://localhost:8080/imfileserver/Upload/Image/
* 图片上传路径 = 基准路径 + 图片名字
* eg.http://localhost:8080/imfileserver/Upload/Image/ wangwu20140821141429
*/
//imgUrl 就是上传的路径 也是下载路径
NSString *imgUrl = [NSString stringWithFormat:@"%@%@",kBaseImageUrl,imageName];
#warning 图片的格式一定jpg(因为我服务器只能上传jpg),一定put方法(我的服务器只能接收put请求)
//发送图片,自定义HttpTool实现上传
HttpTool *httpTool = [[HttpTool alloc] init];
[httpTool uploadData:UIImageJPEGRepresentation(image, 0.7) url:[NSURL URLWithString:imgUrl] progressBlock:nil completion:^(NSError *error) {
if (error == nil) {
JPLogInfo(@"上传成功");
//上传成功,发送消息给好友
NSString *body = [NSString stringWithFormat:@"img:%@",imgUrl];
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
[message addBody:body];
[xmppDelegate.xmppStream sendElement:message];
}
}];
}
相关自定义类
NSDate+JP.h
// .h
#import "NSDate+JP.h"
NSString *const JPDateFormatyyyyMMddHHmmss = @"yyyyMMddHHmmss";//年月日时分秒
NSString *const JPDateFormatMMddHHmmss = @"MMddHHmmss";//月日时分秒
NSString *const JPDateFormatHHmmss = @"HHmmss";//时分秒
@implementation NSDate (JP)
+(NSString *)nowDateFormat:(NSString *)format{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = format;
return [formatter stringFromDate:[NSDate date]];
}
@end
// .m
#import <Foundation/Foundation.h>
//extern常用于定义常量 其常量本身的内容在其它位置定义
extern NSString *const JPDateFormatyyyyMMddHHmmss;//年月日时分秒
extern NSString *const JPDateFormatMMddHHmmss;//月日时分秒
extern NSString *const JPDateFormatHHmmss;//时分秒
@interface NSDate (JP)
/**
* 返回格式化后的字符串 如果201401011212(年月时分秒)
*/
+(NSString *)nowDateFormat:(NSString *)format;
@end
HttpTool
// .h
#import <Foundation/Foundation.h>
typedef void (^HttpToolProgressBlock)(CGFloat progress);
typedef void (^HttpToolCompletionBlock)(NSError *error);
@interface HttpTool : NSObject
/**
上传数据
*/
-(void)uploadData:(NSData *)data
url:(NSURL *)url
progressBlock : (HttpToolProgressBlock)progressBlock
completion:(HttpToolCompletionBlock) completionBlock;
/**
下载数据
*/
-(void)downLoadFromURL:(NSURL *)url
progressBlock : (HttpToolProgressBlock)progressBlock
completion:(HttpToolCompletionBlock) completionBlock;
-(NSString *)fileSavePath:(NSString *)fileName;
@end
// .m
#import "HttpTool.h"
#define kTimeOut 5.0
@interface HttpTool()<NSURLSessionDownloadDelegate,NSURLSessionTaskDelegate>{
//下载
HttpToolProgressBlock _dowloadProgressBlock;
HttpToolCompletionBlock _downladCompletionBlock;
NSURL *_downloadURL;
//上传
HttpToolProgressBlock _uploadProgressBlock;
HttpToolCompletionBlock _uploadCompletionBlock;
}
@end
@implementation HttpTool
#pragma mark - 上传
-(void)uploadData:(NSData *)data url:(NSURL *)url progressBlock:(HttpToolProgressBlock)progressBlock completion:(HttpToolCompletionBlock)completionBlock{
NSAssert(data != nil, @"上传数据不能为空");
NSAssert(url != nil, @"上传文件路径不能为空");
_uploadProgressBlock = progressBlock;
_uploadCompletionBlock = completionBlock;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:kTimeOut];
request.HTTPMethod = @"PUT";
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//NSURLSessionDownloadDelegate
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
//定义下载操作
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data];
[uploadTask resume];
}
#pragma mark - 上传代理
#pragma mark - 上传进度
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
if (_uploadProgressBlock) {
CGFloat progress = (CGFloat) totalBytesSent / totalBytesExpectedToSend;
_uploadProgressBlock(progress);
}
}
#pragma mark - 上传完成
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (_uploadCompletionBlock) {
_uploadCompletionBlock(error);
_uploadProgressBlock = nil;
_uploadCompletionBlock = nil;
}
}
#pragma mark - 下载
-(void)downLoadFromURL:(NSURL *)url
progressBlock:(HttpToolProgressBlock)progressBlock
completion:(HttpToolCompletionBlock)completionBlock{
NSAssert(url != nil, @"下载URL不能传空");
_downloadURL = url;
_dowloadProgressBlock = progressBlock;
_downladCompletionBlock = completionBlock;
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:kTimeOut];
//session 大多数使用单例即可
NSURLResponse *response = nil;
//发达同步请求
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
//NSLog(@"%lld",response.expectedContentLength);
if (response.expectedContentLength <= 0) {
if (_downladCompletionBlock) {
NSError *error =[NSError errorWithDomain:@"文件不存在" code:404 userInfo:nil];
_downladCompletionBlock(error);
//清除block
_downladCompletionBlock = nil;
_dowloadProgressBlock = nil;
}
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//NSURLSessionDownloadDelegate
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
//定义下载操作
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
[downloadTask resume];
}
#pragma mark -NSURLSessionDownloadDelegate
#pragma mark 下载完成
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
//图片保存在沙盒的Doucument下
NSString *fileSavePath = [self fileSavePath:[_downloadURL lastPathComponent]];
//文件管理
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager copyItemAtURL:location toURL:[NSURL fileURLWithPath:fileSavePath] error:nil];
if (_downladCompletionBlock) {
//通知下载成功,没有没有错误
_downladCompletionBlock(nil);
//清空block
_downladCompletionBlock = nil;
_dowloadProgressBlock = nil;
}
}
#pragma mark 下载进度
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
if (_dowloadProgressBlock) {
//已写数据字节数除以总字节数就是下载进度
CGFloat progress = (CGFloat)totalBytesWritten / totalBytesExpectedToWrite;
_dowloadProgressBlock(progress);
}
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
}
#pragma mark -传一个文件名,返回一个在沙盒Document下的文件路径
-(NSString *)fileSavePath:(NSString *)fileName{
NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
//图片保存在沙盒的Doucument下
return [document stringByAppendingPathComponent:fileName];
}
@end