iOS XMPP——消息列表與發(fā)消息

  • 1尾膊、XMPPFrame.h頭開啟下面代碼
// 添加消息模塊
#import "XMPPMessageArchiving.h"
#import "XMPPMessageArchivingCoreDataStorage.h"
  • 2斩松、在AppDelegate.h頭文件中,加入以下屬性
// 消息模塊
@property (nonatomic, strong,readonly) XMPPMessageArchiving *msgArching;
// 消息數(shù)據(jù)存儲
@property (nonatomic, strong,readonly)XMPPMessageArchivingCoreDataStorage *msgArchingStorage;

消息列表展示

  • 需求:創(chuàng)建控制器,將消息列表 展示數(shù)據(jù) 到 tableView上
  • 1、 控制器中導(dǎo)入頭文件 #import "JPAppDelegate.h"
  • 2怎囚、展示消息列表數(shù)據(jù)
#import "JPChatViewController.h"
#import "JPAppDelegate.h"
#import "UIImageView+WebCache.h"

@interface JPChatViewController ()<NSFetchedResultsControllerDelegate, UIImagePickerControllerDelegate>{
    NSFetchedResultsController *_resultContr;//數(shù)據(jù)庫查詢結(jié)果控制器
}
@end

@implementation JPChatViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Do any additional setup after loading the view.

    //數(shù)據(jù)綁定到tableview
    [self dataBind];
}

- (void)dataBind{
    //1.上下文
    NSManagedObjectContext *context = xmppDelegate.msgArchingStorage.mainThreadManagedObjectContext;

    //2.查詢請求(查詢哪張表)
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"];

    //3.設(shè)置排序(時間升序)
    NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:YES];

    request.sortDescriptors = @[timeSort];

    //4.過濾條件(當(dāng)前登錄用戶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];

    //設(shè)置代理
    _resultContr.delegate = self;

    //執(zhí)行請求
    NSError *error = nil;

    [_resultContr performFetch:&error];

    if (error) {
        JPLogError(@"%@",error);
    }
}

#pragma mark -table的數(shù)據(jù)源

- (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];

//    //自己發(fā)送的消息
//    if ([chatMessage.outgoing boolValue]) {
//        //設(shè)置消息內(nèi)容
//        cell.textLabel.text =[NSString stringWithFormat:@"me:%@",chatMessage.body];
//    }else{//好友發(fā)送的消息
//    
//     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(@"無圖片");

        //設(shè)置消息內(nèi)容
        cell.textLabel.text =chatMessage.body;

        //消除圖片
        cell.imageView.image = nil;
    }

    return  cell;
}
@end

發(fā)消息

  • [xmppDelegate.xmppStream sendElement:message];
//發(fā)送消息
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
    NSString *text = textField.text;
    
//    //添加圖片標(biāo)識
//    NSString *imageText = [NSString stringWithFormat:@"img:%@",text];
//    JPLogInfo(@"%@",imageText);
//    
//    //音頻標(biāo)識
//    NSString *soundText = [NSString stringWithFormat:@"sound:%@",text];
//    JPLogInfo(@"%@",imageText);
    
    //封裝消息對象
    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
    [message addBody:text];
    
    //所有跟根據(jù)通信的話,用XMPPStream
    //發(fā)送消息
    [xmppDelegate.xmppStream sendElement:message];
    
    //消除文字
    textField.text = nil;
    return YES;
}
發(fā)送圖片:
  • 打開相冊 選擇圖片
UIImagePickerController *imagePicker =[[UIImagePickerController alloc] init];
        imagePicker.delegate = self;
        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        
        [self presentViewController:imagePicker animated:YES completion:nil];
  • 選擇到圖片從相冊中,往文件服務(wù)器上傳圖片桥胞,然后把圖片完整鏈接發(fā)給通信好友
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    NSLog(@"%@",info);
    
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    
    //銷毀圖片選擇控制器
    [self dismissViewControllerAnimated:YES completion:nil];
    
    //往文件服務(wù)器上傳圖片
    //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);
    
    /**
     * 基準(zhǔn)路徑 http://localhost:8080/imfileserver/Upload/Image/
     * 圖片上傳路徑 = 基準(zhǔn)路徑 + 圖片名字
     * eg.http://localhost:8080/imfileserver/Upload/Image/ wangwu20140821141429
     */
    
    //imgUrl 就是上傳的路徑 也是下載路徑
    NSString *imgUrl = [NSString stringWithFormat:@"%@%@",kBaseImageUrl,imageName];
#warning 圖片的格式一定jpg(因為我服務(wù)器只能上傳jpg),一定put方法(我的服務(wù)器只能接收put請求)
    //發(fā)送圖片,自定義HttpTool實現(xiàn)上傳
    HttpTool *httpTool = [[HttpTool alloc] init];
    [httpTool uploadData:UIImageJPEGRepresentation(image, 0.7) url:[NSURL URLWithString:imgUrl] progressBlock:nil completion:^(NSError *error) {
        if (error == nil) {
            JPLogInfo(@"上傳成功");
            //上傳成功,發(fā)送消息給好友
            NSString *body = [NSString stringWithFormat:@"img:%@",imgUrl];
            
            XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJid];
            [message addBody:body];
            [xmppDelegate.xmppStream sendElement:message];
        }
    }];
}

相關(guān)自定義類

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常用于定義常量 其常量本身的內(nèi)容在其它位置定義
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

/**
 上傳數(shù)據(jù)
 */
-(void)uploadData:(NSData *)data
              url:(NSURL *)url
    progressBlock : (HttpToolProgressBlock)progressBlock
            completion:(HttpToolCompletionBlock) completionBlock;

/**
 下載數(shù)據(jù)
 */
-(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, @"上傳數(shù)據(jù)不能為空");
    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 - 上傳進(jìn)度
-(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 大多數(shù)使用單例即可
    
    NSURLResponse *response = nil;
    
    
    //發(fā)達(dá)同步請求
    [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 下載進(jìn)度
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    
    
    if (_dowloadProgressBlock) {
        //已寫數(shù)據(jù)字節(jié)數(shù)除以總字節(jié)數(shù)就是下載進(jìn)度
        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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缎罢,隨后出現(xiàn)的幾起案子伊群,更是在濱河造成了極大的恐慌考杉,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舰始,死亡現(xiàn)場離奇詭異崇棠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)丸卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門枕稀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谜嫉,你說我怎么就攤上這事萎坷。” “怎么了沐兰?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵哆档,是天一觀的道長。 經(jīng)常有香客問我住闯,道長瓜浸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任比原,我火速辦了婚禮插佛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘春寿。我一直安慰自己朗涩,他們只是感情好忽孽,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布绑改。 她就那樣靜靜地躺著,像睡著了一般兄一。 火紅的嫁衣襯著肌膚如雪厘线。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天出革,我揣著相機(jī)與錄音造壮,去河邊找鬼。 笑死骂束,一個胖子當(dāng)著我的面吹牛耳璧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播展箱,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼旨枯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了混驰?” 一聲冷哼從身側(cè)響起攀隔,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤皂贩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昆汹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體明刷,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年满粗,在試婚紗的時候發(fā)現(xiàn)自己被綠了辈末。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡败潦,死狀恐怖本冲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情劫扒,我是刑警寧澤檬洞,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站沟饥,受9級特大地震影響添怔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贤旷,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一广料、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幼驶,春花似錦艾杏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氏淑,卻和暖如春勃蜘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背假残。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工缭贡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辉懒。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓阳惹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親眶俩。 傳聞我的和親對象是個殘疾皇子莹汤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容