本人有若干成套學習視頻, 可試看! 可試看! 可試看, 重要的事情說三遍 包含Java
, 數據結構與算法
, iOS
, 安卓
, python
, flutter
等等, 如有需要, 聯系微信tsaievan
.
看了一下 XMPPFramework 的源碼,真心看不懂啊,還是繼續我們簡單的內容吧
無論是使用單聊還是群聊, 我們都必須將三大節點之一的 message 節點加入到 XMPPStream 流中,這是完成消息傳輸的最重要的一步
其實,有這一步之后,我們的聊天消息是可以發送成功的,代碼如下:
我們在 textField 的文本輸入的文本取出,初始化消息 XMPPMessage 對象,再加入流中,就完成了消息的發送
#pragma mark *** textField代理 API ***
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
/* 初始化一個聊天模型 */
/**
* 第一個參數: 聊天類型,"chat"表示單聊
* 第二個參數: 聊天對象, 即聊天消息發送給誰
*/
XMPPMessage *message = [[XMPPMessage alloc]initWithType:@"chat" to:self.jid];
/* 添加聊天內容 */
[message addBody:textField.text];
/* 發送消息 */
[kYFXMPPManager.xmppstream sendElement:message];
/* 發送完畢之后清空文本 */
textField.text = nil;
[textField resignFirstResponder];
return YES;
}
我們在另外一個客戶端給這個賬號發送消息,可以發現兩個代理方法都可以回調成功,控制臺都有相應的日志輸出
// -------- 流發送消息成功 --------
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
{
NSLog(@"消息發送成功");
!self.messageSendBlock ? :self.messageSendBlock(message);
}
// -------- 流接收消息成功 --------
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSLog(@"消息接收成功");
!self.messageReceiveBlock ? :self.messageReceiveBlock(message);
}
那么為什么在聊天界面不顯示消息信息呢?那是因為我們的消息只存在 XMPPStream 流中,并沒有進行數據持久化, 如果要做數據持久化的話,必須添加消息歸檔模塊,這里涉及到的一個關鍵類就是“消息歸檔類”---
XMPPMessageArchiving
我們將這個模塊添加到 XMPPStream 中就相當于將流截獲,進行數據->模型的轉換,然后用 CoreData框架保存在本地
斜體部分的功能 XMPPframework 框架已經幫我們完成
#import "YFXMPPManager+MessageArchive.h"
@implementation YFXMPPManager (MessageArchive)
- (void)addMessageArchivingModule
{
/* 初始化 */
self.xmppmessageArchiving = [[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:[XMPPMessageArchivingCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_main_queue()];
/* 無需配置 */
/* 激活 */
[self.xmppmessageArchiving activate:self.xmppstream];
}
@end
這樣,我們在展示聊天信息的時候,就可以舒舒服服地使用 NSFetchResultsController 了
懶加載NSFetchResultsController(初始化)
#pragma mark *** Getter & Setter ***
- (NSFetchedResultsController *)fetchedResultsController
{
if (!_fetchedResultsController) {
/* 初始化查詢請求 */
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:YES]];
/* 設置謂詞,只顯示當前聊天者的聊天記錄 */
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"bareJidStr == %@",self.jid.bare];
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:[XMPPMessageArchivingCoreDataStorage sharedInstance].mainThreadManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
/* 執行查詢 */
[_fetchedResultsController performFetch:nil];
/* 刷新 tableView */
[self.tableView reloadData];
}
return _fetchedResultsController;
}
其實單聊和群聊是大同小異的, 有一點不同的就是,房間是要單獨創建的,不然群聊在哪里進行呢?房間的創建又需要一個新的 JID,和 nickname,創建成功后,有代理方法的回調,在代理方法中完成房間配置和邀請
房間創建過程
#import "YFXMPPGroupChatManager.h"
#import "YFXMPPManager.h"
@implementation YFXMPPGroupChatManager
+ (instancetype)sharedManager
{
static id instanceType = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instanceType = [[YFXMPPGroupChatManager alloc]init];
});
return instanceType;
}
/**
* @param jid 房間的 Jid
* @param nickname 房間的昵稱
*/
- (void)joinRoomWithJid:(XMPPJID *)jid andNickname:(NSString *)nickname
{
/* 初始化房間 */
self.xmppRoom = [[XMPPRoom alloc]initWithRoomStorage:[XMPPRoomCoreDataStorage sharedInstance] jid:jid dispatchQueue:dispatch_get_main_queue()];
/* 配置,無需配置 */
/* 只需要添加一個代理 */
[self.xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
/* 激活 */
[self.xmppRoom activate:kYFXMPPManager.xmppstream];
/**
* @參數1:nickname
* @參數2:歷史記錄,填寫 nil, 表示不獲取歷史記錄
*/
/* 如果加入的房間在服務器中不存在,則創建,如果存在,就直接加入 */
[self.xmppRoom joinRoomUsingNickname:nickname history:nil];
}
#pragma mark *** Getter & Setter ***
// -------- 創建房間成功之后一定要做兩件事情,否則房間無法使用 --------
/**
* 1. 配置房間
* 2. 邀請人到房間
*/
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
{
/* 配置房間 */
[sender configureRoomUsingOptions:nil];
/* 查詢房間配置 */
[sender fetchConfigurationForm];
/* 邀請人到房間 */
/**
* 參數1: 邀請對象的 jid
* 參數2: 邀請信息
*/
[sender inviteUser:[XMPPJID jidWithUser:@"tsaievan" domain:@"tsaievan.com" resource:nil] withMessage:@"今天晚上放學別走"];
[sender inviteUser:[XMPPJID jidWithUser:@"caiyifan" domain:@"tsaievan.com" resource:nil] withMessage:@"今晚放學別走"];
[sender inviteUser:[XMPPJID jidWithUser:@"mary" domain:@"tsaievan.com" resource:nil] withMessage:@"今天晚上放學請你喝紅牛"];
}
// -------- 房間加入成功 --------
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
/* 配置房間 */
[sender configureRoomUsingOptions:nil];
/* 查詢房間配置 */
[sender fetchConfigurationForm];
/* 邀請人到房間 */
/**
* 參數1: 邀請對象的 jid
* 參數2: 邀請信息
*/
[sender inviteUser:[XMPPJID jidWithUser:@"tsaievan" domain:@"tsaievan.com" resource:nil] withMessage:@"今天晚上放學別走"];
[sender inviteUser:[XMPPJID jidWithUser:@"caiyifan" domain:@"tsaievan.com" resource:nil] withMessage:@"今晚放學別走"];
[sender inviteUser:[XMPPJID jidWithUser:@"mary" domain:@"tsaievan.com" resource:nil] withMessage:@"今天晚上放學請你喝紅牛"];
}
// -------- 房間解散成功 --------
- (void)xmppRoomDidLeave:(XMPPRoom *)sender
{
}
@end
單聊和群聊的過程基本上就是這樣,但是在實際寫代碼的時候還是會遇到很多坑,大家還是要自己敲一遍才可以深刻體會。