首先去融云開發(fā)者注冊(cè)一波賬號(hào),獲取AppKey :
然后拉取融云SDK:
platform :ios, '8.0'
inhibit_all_warnings!
target 'your projectName' do
pod 'RongCloudIM/IMKit'
end
然后pod install友鼻,會(huì)發(fā)現(xiàn)SDK已經(jīng)被你拉取下來了,首先在程序入口AppDelegate.m里初始化融云SDK:
[[RCIM sharedRCIM]initWithAppKey:kRongCloudKey];
[RCIM sharedRCIM].connectionStatusDelegate = self;
[RCIM sharedRCIM].enablePersistentUserInfoCache = YES;
[RCIM sharedRCIM].globalConversationAvatarStyle = RC_USER_AVATAR_CYCLE;
[RCIM sharedRCIM].globalMessageAvatarStyle =RC_USER_AVATAR_CYCLE;
[RCIM sharedRCIM].showUnkownMessageNotificaiton = YES;
[RCIM sharedRCIM].enableMessageAttachUserInfo = YES;
[RCIM sharedRCIM].userInfoDataSource = self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectToRongCloud) name:kLoginSucessNotification object:nil];
// MARK: - RCIMUserInfoDataSource
- (void)getUserInfoWithUserId:(NSString *)userId completion:(void (^)(RCUserInfo *userInfo))completion {
NSLog(@"Rong cloud userID: %@", userId);
if ([userId isEqualToString:kAppUserInfo.userId]) {
RCUserInfo *user = [[RCUserInfo alloc] initWithUserId:userId
name:kAppUserInfo.name
portrait:nil];
//緩存至用戶信息
[kRongCloudManager insertWithUser:user];
completion(user);
} else {
__block RCUserInfo *user;
//根據(jù)userId去查找相對(duì)應(yīng)的頭像和昵稱,緩存
[NetTool postWithURLString:[NSString stringWithFormat:@"%@%@",kBaseURL,@"rongCloud/getUserNameAndImage"]
parameters: [UtilityHelper encryptParmar:@{@"uid":userId}]
success:^(NSDictionary *data) {
if ([data[@"reCode"] isEqualToString:@"X0000"]) {
user = [[RCUserInfo alloc] initWithUserId:userId
name:data[@"rel"][@"name"]
portrait:[data[@"rel"][@"image"]length] > 2 ? data[@"rel"][@"image"]: nil];
//緩存至用戶信息
[kRongCloudManager insertWithUser:user];
completion(user);
} else {
completion(user);
}
} failure:^(NSError *error) {
completion(user);
}];
}
}
然后在App的登錄那里將后臺(tái)獲取到的融云token信息拿過來去連接融云服務(wù)器:
// MARK: - 融云服務(wù)器連接狀態(tài)監(jiān)聽
- (void)onRCIMConnectionStatusChanged:(RCConnectionStatus)status {
if (status == ConnectionStatus_Connected) {
NSLog(@"融云服務(wù)器連接成功!");
} else {
if (status == ConnectionStatus_SignUp) {
NSLog(@"融云服務(wù)器斷開連接!");
} else {
NSLog(@"融云服務(wù)器連接失敗!");
}
}
}
// MARK: - 連接融云服務(wù)器
- (void)connectToRongCloud {
[NetTool postWithURLString:[NSString stringWithFormat:@"%@%@",kBaseURL,@"rongCloud/getRongCloudToken"]
parameters:@{@"token":kUserToken}
success:^(NSDictionary *data) {
if ([data[@"reCode"] isEqualToString:@"X0000"]) {
NSString *rongCloudToken = data[@"rel"];
[[NSUserDefaults standardUserDefaults] setObject:rongCloudToken forKey:@"RCToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[RCIM sharedRCIM] connectWithToken:rongCloudToken
success:^(NSString *userId) {
//設(shè)置當(dāng)前用戶信息
RCUserInfo *currentUserInfo = [[RCUserInfo alloc] initWithUserId:kAppUserInfo.userId
name:kAppUserInfo.name
portrait:kRandomAvatar];
[RCIM sharedRCIM].currentUserInfo = currentUserInfo;
[RCIM sharedRCIM].enablePersistentUserInfoCache = YES;
} error:^(RCConnectErrorCode status) {
} tokenIncorrect:^{
}];
}
} failure:^(NSError *error) {
}];
}
在登錄的頁(yè)面那里發(fā)一個(gè)通知給App廊谓,拿到Token去連接融云的服務(wù)器:
[[NSNotificationCenter defaultCenter] postNotificationName:kLoginSucessNotification object:nil];
看融云給出的打印日志會(huì)發(fā)現(xiàn)梳猪,融云的集成是成功了:
接下來就是聊天模塊了,仔細(xì)看SDK的頭文件你會(huì)發(fā)現(xiàn)蒸痹,其實(shí)融云的程序猿早就寫好了這些模塊春弥,如果不是高度自定義的話,完全可以new一個(gè)VController繼承他寫好的控制器电抚,其中最核心的兩個(gè)viewController:RCConversationViewController惕稻、RCConversationListViewController,顧明思義,第一個(gè)是用來展示聊天會(huì)話的蝙叛,第二個(gè)是用來展示繪畫列表的俺祠。
具體的實(shí)現(xiàn)代碼如下:
@interface CustomChatListVC () <RCIMReceiveMessageDelegate,UITableViewDataSource,UITableViewDelegate> {
UITableView *_tableView;
NSMutableArray <RCConversation *> * _conversationListArray;
}
@end
@implementation CustomChatListVC
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self refresh];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
_conversationListArray = [NSMutableArray arrayWithArray:[[RCIMClient sharedRCIMClient] getConversationList:@[@(ConversationType_PRIVATE)]]];
[RCIM sharedRCIM].receiveMessageDelegate = self;
_tableView = kTableViewWithConfiguration(self.view, CGRectZero, 0, self, self, nil);
[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
}
// MARK: - refreshAction
- (void)refresh {
_conversationListArray = [NSMutableArray arrayWithArray:[[RCIMClient sharedRCIMClient] getConversationList:@[@(ConversationType_PRIVATE)]]];
for (RCConversation *conversation in _conversationListArray) {
__block RCUserInfo *user;
[NetTool postWithURLString:[NSString stringWithFormat:@"%@%@",kBaseURL,@"rongCloud/getUserNameAndImage"]
parameters: [UtilityHelper encryptParmar:@{@"uid":conversation.targetId}]
success:^(NSDictionary *data) {
if ([data[@"reCode"] isEqualToString:@"X0000"]) {
user = [[RCUserInfo alloc] initWithUserId:conversation.targetId
name:data[@"rel"][@"name"]
portrait:[data[@"rel"][@"image"]length] > 2 ? data[@"rel"][@"image"]: nil];
[kRongCloudManager insertWithUser:user];
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
}
} failure:^(NSError *error) {
}];
}
}
- (RCUserInfo *)getSenderInfoWithExtra:(NSString *)extraStr targetId:(NSString *)targetId {
NSDictionary *json = [extraStr mj_JSONObject];
return [[RCUserInfo alloc] initWithUserId:targetId name:json[@"name"] portrait:json[@"avatar"]];
}
// MARK: - 接收到消息的回調(diào)
- (void)onRCIMReceiveMessage:(RCMessage *)message left:(int)left {
/*NSInteger index = 0;
BOOL exsit = NO;
for (int i = 0 ; i < _conversationListArray.count; i ++) {
RCConversation *conversation = _conversationListArray[i];
if ([conversation.targetId isEqualToString:message.targetId]) {
exsit = YES;
index = i;
break;
}
}
if (exsit) {
//存在
RCConversation *conversation = _conversationListArray[index];
conversation.lastestMessage = message.content;
conversation.unreadMessageCount ++;
[_conversationListArray replaceObjectAtIndex:index withObject:conversation];
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
});
} else {
RCConversation *newConversation = [RCConversation new];
newConversation.lastestMessage = message.content;
newConversation.targetId = message.targetId;
newConversation.senderUserId = message.senderUserId;
newConversation.receivedTime = message.receivedTime;
newConversation.unreadMessageCount ++;
[_conversationListArray addObject:newConversation];
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
}*/
[self refresh];
}
// MARK: - UITableVieDataSource &Delegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _conversationListArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatListCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([ChatListCell class])];
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([ChatListCell class]) owner:self options:nil] firstObject];
}
[cell setConversationListModel:_conversationListArray[indexPath.row]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
RCConversation *model = _conversationListArray[indexPath.row];
model.unreadMessageCount = 0;
[_conversationListArray replaceObjectAtIndex:indexPath.row withObject:model];
CustomChatVC *conversationVC = [[CustomChatVC alloc]initWithConversationType:model.conversationType targetId:model.targetId];
conversationVC.title = [kRongCloudManager getUserWithTargetId:model.targetId].name;
[self.navigationController pushViewController:conversationVC animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 80;
}
自定義列表cell:
@implementation ChatListCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
//已讀已發(fā)送
_tip.clipsToBounds = YES;
_tip.layer.borderWidth = 1.0;
_tip.layer.cornerRadius = 4.0;
//頭像
_avatar.clipsToBounds = YES;
_avatar.layer.cornerRadius = _avatar.height / 2.0;
//未讀消息
_remindCount.clipsToBounds = YES;
_remindCount.layer.cornerRadius = _remindCount.height / 2.0;
_remindCount.hidden = YES;
}
/*
- (void)setDataWithConversationListModel:(ConversationListModel *)conversationListModel {
RCConversation *model = conversationListModel.conversation;
if (model.unreadMessageCount == 0 ) {
_remindCount.hidden = YES;
} else {
_remindCount.hidden = NO;
_remindCount.text = [NSString stringWithFormat:@"%i",model.unreadMessageCount];
}
if (model.receivedStatus == ReceivedStatus_READ) {
//已讀
_tip.layer.borderColor = [UIColor greenColor].CGColor;
_tip.textColor = [UIColor greenColor];
_tip.text = @"已讀";
} else {
_tip.layer.borderColor = [UIColor redColor].CGColor;
_tip.textColor = [UIColor redColor];
_tip.text = @"送達(dá)";
}
RCUserInfo *sender = [kRongCloudManager getUserWithTargetId:model.targetId];
[_avatar sd_setImageWithURL:[NSURL URLWithString:sender.portraitUri] placeholderImage:[UIImage imageWithColor:[UIColor grayColor] withSize:CGSizeMake(60, 60)]];
//名字
_name.text = sender.name;
//職位名稱
_position.text = sender.name;
_message.text = [model.lastestMessage valueForKey:@"_content"];
NSDateFormatter *format = [NSDateFormatter new];
BOOL today = [[NSCalendar currentCalendar] isDateInToday:[NSDate dateWithTimeIntervalSince1970:model.receivedTime/1000]];
if (today) {
[format setDateFormat:@"HH:MM"];
} else {
[format setDateFormat:@"yyyy-MM-dd"];
}
_time.text = [format stringFromDate:[NSDate dateWithTimeIntervalSince1970:model.receivedTime/1000]];
}
*/
// MARK: - private Method
- (void)setConversationListModel:(RCConversation *)model {
if (model.unreadMessageCount == 0 ) {
_remindCount.hidden = YES;
} else {
_remindCount.hidden = NO;
_remindCount.text = [NSString stringWithFormat:@"%i",model.unreadMessageCount];
}
if (model.receivedStatus == ReceivedStatus_READ) {
//已讀
_tip.layer.borderColor = [UIColor greenColor].CGColor;
_tip.textColor = [UIColor greenColor];
_tip.text = @"已讀";
} else {
_tip.layer.borderColor = [UIColor redColor].CGColor;
_tip.textColor = [UIColor redColor];
_tip.text = @"送達(dá)";
}
// RCUserInfo *sender = [self getSenderInfoWithExtra:[model.lastestMessage valueForKey:@"_extra"] targetId:model.targetId];
RCUserInfo *sender = [kRongCloudManager getUserWithTargetId:model.targetId];
//頭像
[_avatar sd_setImageWithURL:[NSURL URLWithString:sender.portraitUri] placeholderImage:[UIImage imageWithColor:[UIColor grayColor] withSize:CGSizeMake(60, 60)]];
//名字
_name.text = sender.name;
//職位名稱
_position.text = sender.name;
BOOL isMe = [model.lastestMessage.senderUserInfo.userId isEqualToString:kAppUserInfo.userId];
NSString *messageContent = [MessageConvert messageConvertWithMessageContent:model.lastestMessage];
_message.text = isMe?[NSString stringWithFormat:@"我:%@",messageContent]: messageContent;
NSDateFormatter *format = [NSDateFormatter new];
BOOL today = [[NSCalendar currentCalendar] isDateInToday:[NSDate dateWithTimeIntervalSince1970:model.receivedTime/1000]];
if (today) {
[format setDateFormat:@"HH:MM"];
} else {
[format setDateFormat:@"yyyy-MM-dd"];
}
_time.text = [format stringFromDate:[NSDate dateWithTimeIntervalSince1970:model.receivedTime/1000]];
}
- (RCUserInfo *)getSenderInfoWithExtra:(NSString *)extraStr targetId:(NSString *)targetId {
NSDictionary *json = [extraStr mj_JSONObject];
return [[RCUserInfo alloc] initWithUserId:targetId name:json[@"name"] portrait:json[@"avatar"]];
}
MessageConvert.m:
+(NSString *)messageConvertWithMessageContent:(RCMessageContent *)messageContent {
NSString *value = @"";
if ([messageContent isKindOfClass:[RCTextMessage class]]) {
//文本
value = ((RCTextMessage *)messageContent).content;
} else if ([messageContent isKindOfClass:[RCLocationMessage class]]) {
//位置
value = @"[位置]";
} else if ([messageContent isKindOfClass:[RCImageMessage class]]) {
//圖片
value = @"[圖片]";
} else if ([messageContent isKindOfClass:[RCVoiceMessage class]]) {
//語音
value = @"[語音]";
} else if ([messageContent isKindOfClass:[RCSightMessage class]]) {
//小視頻
value = @"[小視頻]";
}
return value;
}
由于繼承自RCConversationListViewController的ViewController只能在dataSource里面添加custom樣式的model,從而達(dá)到增加自定義cell的效果:
-(NSMutableArray *)willReloadTableData:(NSMutableArray *)dataSource {
NSArray *customItems = @[@"系統(tǒng)消息1",@"系統(tǒng)消息2"];
for (int i = 0; i<customItems.count; i++) {
RCConversationModel *model = [RCConversationModel new];
model.conversationTitle = customItems[i];
model.conversationModelType = RC_CONVERSATION_MODEL_TYPE_CUSTOMIZATION;
model.isTop = YES;
if (dataSource.count) {
//插入自定義cell
[dataSource insertObject:model atIndex:i];
}
}
return dataSource;
}
- (void)onSelectedTableRow:(RCConversationModelType)conversationModelType
conversationModel:(RCConversationModel *)model
atIndexPath:(NSIndexPath *)indexPath {
if (model.conversationModelType == RC_CONVERSATION_MODEL_TYPE_CUSTOMIZATION) {
//自定義消息cell的點(diǎn)擊
} else {
//系統(tǒng)會(huì)話列表cell的點(diǎn)擊
}
}
- (RCConversationBaseCell *)rcConversationListTableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SystemChatListCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([SystemChatListCell class])];
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([SystemChatListCell class]) owner:self options:nil] firstObject];
}
//系統(tǒng)消息cell的配置
return cell;
}
這個(gè)剛開始發(fā)現(xiàn)的時(shí)候借帘,感覺有點(diǎn)坑蜘渣,他不像環(huán)信那樣可以直接去重寫baseCell里面的東西(只能添加,而不能修改肺然,因?yàn)檫@個(gè)VC繼承了RCConversationListViewController)蔫缸,各位大兄弟要注意這個(gè)地方。
在聊天室要用到自定義的cell际起,所有我們要重寫一個(gè)message消息類集成于RCMessageContent拾碌,重寫一個(gè)Cell繼承RCMessageCell,具體如下:
#import <RongIMKit/RongIMKit.h>
#import "JobMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface JobCell : RCMessageCell
@property(nonatomic, strong) UIImageView *bubbleBackgroundView;
-(void)setDataModel:(RCMessageModel *)model;
//+ (CGSize)bubbleSizeWithJobMessageModel:(JobMessage *)model;
@end
NS_ASSUME_NONNULL_END
#import "JobCell.h"
@interface JobCell () {
UILabel *_titles[7];
}
@end
@implementation JobCell
+ (CGSize)sizeForMessageModel:(RCMessageModel *)model
withCollectionViewWidth:(CGFloat)collectionViewWidth
referenceExtraHeight:(CGFloat)extraHeight {
return CGSizeMake(kScreenWidth, 300 + extraHeight);
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initialize];
}
return self;
}
- (void)initialize {
self.bubbleBackgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
self.bubbleBackgroundView.backgroundColor = [UIColor whiteColor];
self.bubbleBackgroundView.clipsToBounds = YES;
self.bubbleBackgroundView.layer.cornerRadius = 5.0;
[self.messageContentView addSubview:self.bubbleBackgroundView];
for (int i = 0 ; i < 7; i ++) {
_titles[i] = kLabelWithCornerRadius(self.bubbleBackgroundView, CGRectMake(20, i == 0 ? 30 :_titles[i - 1].bottom + 10, 280, 35), [UIColor whiteColor], [UIColor blackColor], 0, kFont(14),@"" , 0.0);
}
self.bubbleBackgroundView.userInteractionEnabled = YES;
UITapGestureRecognizer *longPress =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self.bubbleBackgroundView addGestureRecognizer:longPress];
}
- (void)tapAction:(UIGestureRecognizer *)gestureRecognizer {
if ([self.delegate respondsToSelector:@selector(didTapMessageCell:)]) {
[self.delegate didTapMessageCell:self.model];
}
}
- (void)setDataModel:(RCMessageModel *)model {
[super setDataModel:model];
JobMessage *message = (JobMessage *)model.content;
NSDictionary *value = [message.content mj_JSONObject][@"data"];
for (int i = 0; i < 7; i ++) {
_titles[i].text = [NSString stringWithFormat:@"%@:%@\n",[value allKeys][i],[value valueForKey:[value allKeys][i]]];
}
if (message) {
}
//拉伸圖片
if (MessageDirection_RECEIVE == self.messageDirection) {
} else {
}
}
+ (CGSize)bubbleSizeWithJobMessageModel:(JobMessage *)message {
return CGSizeMake(300, 300);
}
JobMessage類:
#import <RongIMLib/RongIMLib.h>
#import <RongIMLib/RCMessageContent.h>
NS_ASSUME_NONNULL_BEGIN
@interface JobMessage : RCMessageContent <NSCoding,RCMessageContentView>
@property(nonatomic,strong)NSString *content;
@property(nonatomic, strong) NSString* extra;
+(instancetype)messageWithContent:(NSString *)jsonContent;
@end
NS_ASSUME_NONNULL_END
@implementation JobMessage
+ (instancetype)messageWithContent:(NSString *)jsonContent {
JobMessage *model = [JobMessage new];
if (model) {
model.content = jsonContent;
}
return model;
}
//存儲(chǔ)狀態(tài)和是否計(jì)入未讀數(shù)
+(RCMessagePersistent)persistentFlag {
//存儲(chǔ)并計(jì)入未讀數(shù)
return (MessagePersistent_ISCOUNTED);
}
#pragma mark – NSCoding protocol methods
#define KEY_TXTMSG_CONTENT @"content"
#define KEY_TXTMSG_EXTRA @"extra"
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.content = [aDecoder decodeObjectForKey:KEY_TXTMSG_CONTENT];
self.extra = [aDecoder decodeObjectForKey:KEY_TXTMSG_EXTRA]; }
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.content forKey:KEY_TXTMSG_CONTENT];
[aCoder encodeObject:self.extra forKey:KEY_TXTMSG_EXTRA];
}
#pragma mark – RCMessageCoding delegate methods
///將消息內(nèi)容編碼成json
-(NSData *)encode {
NSMutableDictionary *dataDict=[NSMutableDictionary dictionary];
[dataDict setObject:self.content forKey:@"content"];
if (self.extra) {
[dataDict setObject:self.extra forKey:@"extra"];
}
NSData *data = [NSJSONSerialization dataWithJSONObject:dataDict
options:kNilOptions
error:nil];
return data;
}
//將json解碼生成消息內(nèi)容
-(void)decodeWithData:(NSData *)data {
__autoreleasing NSError* __error = nil;
if (!data) {
return;
}
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&__error];
NSLog(@"dictionary == %@",dictionary);
if ([dictionary objectForKey:@"content"]) {
self.content = dictionary[@"content"];
NSLog(@"dictionary1111 == %@",dictionary[@"content"]);
self.extra = dictionary[@"extra"];
}else{
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:kNilOptions error:nil];
NSString *content ;
if (!data) {
NSLog(@"%@",error);
}else{
content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}
self.content = content;
}
}
//您定義的消息類型名,需要在各個(gè)平臺(tái)上保持一致街望,以保證消息互通,別以 RC 開頭校翔,以免和融云系統(tǒng)沖突
+(NSString *)getObjectName {
return @"JobMessageType";
}
//最后一條消息是自定義消息的時(shí)候,可以更改在會(huì)話列表顯示的類型灾前,為了區(qū)分消息類型
- (NSString *)conversationDigest {
NSString *contentStr = @"[職位信息]";
return contentStr;
}
@end
然后在ChatVC里注冊(cè)對(duì)應(yīng)的message消息類和messageCell類:
[self registerClass:[JobCell class] forMessageClass:[JobMessage class]];
在AppDelegate里面注冊(cè)一波自定義message類型:
[[RCIM sharedRCIM] registerMessageType:[JobMessage class]];
這里特別補(bǔ)充一下關(guān)于用戶頭像和昵稱的問題防症,由于和環(huán)信一樣,這種IM三方并不負(fù)責(zé)存儲(chǔ)用戶或群組信息哎甲,這些東西一般是用來存放在自己App的后臺(tái)服務(wù)器上蔫敲,在加載會(huì)話列表的時(shí)候需要去后臺(tái)根據(jù)targetId去拉取聊天對(duì)話的用戶信息,但是有一種更為巧妙的方法就是將發(fā)送者的信息(昵稱炭玫、頭像奈嘿、職位名稱等等)存放在消息體中,消息體中有一個(gè)字段叫做extra:
{"content":"測(cè)試","extra":{
"name":"Chan",
"avatar":"http://xxxx/pic_201808241707108698543.png"}
}
然后根據(jù)每條消息的latestMessage.extra字段獲取最新一條消息的用戶信息吞加,但是注意裙犹,這里有一個(gè)問題就是加入我一直給一個(gè)用戶發(fā)送消息酝惧,但是對(duì)方?jīng)]回復(fù),這時(shí)候就不管用了伯诬,所以讀者也注意到了我上面的代碼,用了一個(gè)單利對(duì)象專門用來緩存對(duì)話targeId的RCUserInfo用戶信息:
#import "RCUserManager.h"
@implementation RCUserManager
+ (instancetype)shareManager {
static RCUserManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[RCUserManager alloc] init];
});
return manager;
}
- (instancetype)init {
if (self = [super init]) {
_users = [NSMutableArray new];
}
return self;
}
- (void)insertWithUser:(RCUserInfo *)user {
if (_users) {
BOOL exsit = NO;
int index = 0;
for (int i = 0 ; i < _users.count; i ++) {
if ([((RCUserInfo *)_users[i]).userId isEqualToString:user.userId]) {
exsit = YES;
index = i;
break;
}
}
if (exsit) {
[_users replaceObjectAtIndex:index withObject:user];
} else {
[_users addObject:user];
}
}
}
- (RCUserInfo *)getUserWithTargetId:(NSString *)targetId {
RCUserInfo *user;
if (_users.count) {
for (int i = 0 ; i < _users.count; i ++) {
RCUserInfo *user = _users[i];
if ([user.userId isEqualToString:targetId]) {
return user;
break;
}
}
}
return user;
}
由于自己的項(xiàng)目是招聘類App巫财,在和企業(yè)溝通的時(shí)候盗似,進(jìn)入聊天室的時(shí)候,會(huì)出現(xiàn)一條企業(yè)發(fā)送過來的職位消息,也就是上面自定義的messageCell:
CustomChatVC *conversationVC = [[CustomChatVC alloc]initWithConversationType:ConversationType_PRIVATE targetId:@"1392428"];
JobInfoModel *jobModel = [JobInfoModel mj_objectWithKeyValues:jsonValue[@"data"]];
conversationVC.jobInfoModel = jobModel;
//插入一條對(duì)方發(fā)送過來的消息
[[RCIMClient sharedRCIMClient] insertIncomingMessage:ConversationType_PRIVATE
targetId:@"1392428"
senderUserId:@"1392428"
receivedStatus:ReceivedStatus_READ
content:[JobMessage messageWithContent:[jsonValue mj_JSONString]]
sentTime:0];
conversationVC.title = @"Chan";
[self.navigationController pushViewController:conversationVC animated:YES];
具體的簡(jiǎn)單實(shí)現(xiàn)就到這里,大致效果如下:
由于聊天室使用的是融云的控制器庄吼,也可以進(jìn)行自定義前痘,但是UI界面方面處理起來比較麻煩,后續(xù)再完善一波昧绣。