- 发消息,有发送的触发界面,一般是输入框,及相关按钮
有展示消息的列表
- NIMKit 设计挺好的
面向协议,结构上的便于替换
本文主要探讨,展示消息
IM 自定制,一般的理解是
自定义消息,分为数据和界面,两部分
- 自定义消息的数据结构
// 自定义消息解析
NIMCustomObject.registerCustomDecoder(IMMsgDecoder())
- 自定义消息的界面
我们看到的聊天记录,就是一个消息列表 , UITableView
// 布局管理器
NIMKit.shared().registerLayoutConfig(IMCellLayoutConfig())
场景,聊天会话界面,需要一套 IM 界面
语音房里面,的半屏幕聊天界面,需要另外一套样式的 IM 界面
即,一款 app 内,同时存在两种 IM 聊天界面
思路一: 简单的,换配置
默认这样注册
// 布局管理器
NIMKit.shared().registerLayoutConfig(IMCellLayoutConfig())
新的聊天样式界面中,
出现,就换新的配置,
消失,就恢复原来的配置
class SessionChatVC: NIMSessionViewController{
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NIMKit.shared().registerLayoutConfig(IMCellLayoutConfigDjz())
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NIMKit.shared().registerLayoutConfig(IMCellLayoutConfig())
}
}
效果是,把文本消息的文字颜色改了
class IMCellLayoutConfigDjz: NIMCellLayoutConfig{
// 重写,自定义cell消息 , contentView
override func cellContent(_ model: NIMMessageModel!) -> String! {
guard model.message.messageType != .text else {
// 看这一行,够了
return NSStringFromClass(NIMSessionTextContentViewDJZ.self)
}
guard model.message.messageType == .custom,
let customAttachment = model.message.messageObject as? NIMCustomObject,
let attachment = customAttachment.attachment
else {
return super.cellContent(model)
}
if attachment.isKind(of: IMGiftsAttachment.self) {
return NSStringFromClass(IMGiftContentView.self)
}else if attachment.isKind(of: IMGifImageAttachment.self) {
return NSStringFromClass(IMGifImageContentView.self)
}
else{
return NSStringFromClass(IMChatUpContentView.self)
}
}
}
NIMSessionTextContentViewDJZ 其他的,与 NIMKit 自带的 NIMSessionTextContentView,相同
@implementation NIMSessionTextContentViewDJZ
- (void)refresh:(NIMMessageModel *)data {
[super refresh:data];
// 消息解码 默认: self.model.message.text
NSString *text = [MMessageTool imMessageTextBase64Decoded:self.model.message];
NIMKitSetting *setting = [[NIMKit sharedKit].config setting:data.message];
// 看这一行
// 出于演示,例子非常的简单
self.textLabel.textColor = UIColor.redColor;
// self.textLabel.textColor = setting.textColor;
self.textLabel.font = setting.font;
[self.textLabel nim_setText:text];
[self.bubbleImageView setHidden: true];
}
@end
思路 2 : 复杂些, 涉及的源代码,多一些
建立聊天界面的子类 NIMSessionViewController
@interface NIMDjzSessionViewCtrl: NIMSessionViewController
@end
简单的,修改聊天界面的背景色: cell 的背景色
聊天界面,样式 A, 背景色 AA
@implementation NIMSessionViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[[NIMKit sharedKit] config] setCellBackgroundColor: NIMKit_UIColorFromRGB(0xf5f5f5)];
}
@end
语音房的聊天界面,样式 Z, 背景色 ZZ
@implementation NIMDjzSessionViewCtrl
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear: animated];
[[[NIMKit sharedKit] config] setCellBackgroundColor: bgColor];
}
@end
修改 TableView 与根视图的背景色
语音房的聊天界面
@implementation NIMDjzSessionViewCtrl
- (void)setupTableView{
self.view.backgroundColor = bgColor;
self.tableView = [[UITableView alloc] initWithFrame: CGRectMake(0, 52, 375, 233) style:UITableViewStylePlain];
self.tableView.backgroundColor = bgColor;
// ...
}
@end
消除语音房的聊天界面,的背景气泡
使用 NIMAdvancedMessageCellDjz
,而不是 NIMAdvancedMessageCell
NIMAdvancedMessageCellDjz 与 NIMAdvancedMessageCell 的区别,在于
@implementation NIMAdvancedMessageCellDjz
- (void)refreshBubblesBackgroundView{
// 隐藏气泡
[self.bubblesBackgroundView setHidden: YES];
}
@end
往上推导,
为了使用 NIMAdvancedMessageCellDjz
,
需要使用 NIMMessageCellFactoryDeng
@implementation NIMMessageCellFactoryDeng
- (NIMMessageCell *)cellInTable:(UITableView*)tableView
forMessageMode:(NIMMessageModel *)model
{
id<NIMCellLayoutConfig> layoutConfig = [[NIMKit sharedKit] layoutConfig];
NSString *identity = [layoutConfig cellContent:model];
NIMMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:identity];
if (!cell) {
// 注意这一行
NSString *clz = @"NIMAdvancedMessageCellDjz";
[tableView registerClass:NSClassFromString(clz) forCellReuseIdentifier:identity];
cell = [tableView dequeueReusableCellWithIdentifier:identity];
}
return (NIMMessageCell *)cell;
}
@end
NIMMessageCellFactoryDeng 与 NIMMessageCellFactory 类似
风格,就如上面
继续推导,
为了使用 NIMMessageCellFactoryDeng
,
需要使用 NIMSessionTableAdapterDeng
@interface NIMSessionTableAdapterDeng()
@property (nonatomic,strong) NIM_djz_MessageCellFactory *cellFactory;
@end
@implementation NIMSessionTableAdapterDeng
- (instancetype)init
{
self = [super init];
if (self) {
_cellFactory = [[NIMMessageCellFactoryDeng alloc] init];
}
return self;
}
@end
NIMSessionTableAdapterDeng 与 NIMSessionTableAdapter 类似
继续推导,
为了使用 NIMSessionTableAdapterDeng
,
需要调整 NIMSessionConfigurator
的源代码
添加属性
@interface NIMSessionConfigurator()
@property (nonatomic,strong) NIM_djz_SessionTableAdapter *tableAdapterDeng;
@end
添加方法
@implementation NIMSessionConfigurator
- (void)setupDeng:(NIMSessionViewController *)vc{
// 上面的,同 setup 方法
_tableAdapterDeng = [[NIMSessionTableAdapterDeng alloc] init];
_tableAdapterDeng.interactor = _interactor;
_tableAdapterDeng.delegate = vc;
vc.tableView.delegate = _tableAdapterDeng;
vc.tableView.dataSource = _tableAdapterDeng;
[vc setInteractor:_interactor];
}
@end
向上推导,
最后,
语音房的半屏幕的聊天界面 , 样式 Z
调用 setupDeng
, 打通
@implementation NIMAdvancedMessageCellDjz
- (void)setupConfigurator{
self.configurator = [[NIMSessionConfigurator alloc] init];
// 注意这一行
[self.configurator setupDeng:self];
BOOL needProximityMonitor = [self needProximityMonitor];
[[NIMSDK sharedSDK].mediaManager setNeedProximityMonitor:needProximityMonitor];
}
@end
NIMKit 并不难,就是功能挺多的,
为了解除耦合,调用绕来绕去的
已经倒着梳理了一遍
再来顺着,梳理一遍
我们看到,聊天视图里面,
有一个 tableView
@interface NIMSessionViewController
@property (nonatomic, strong) UITableView *tableView;
@end
聊天视图里面的配置代码
@implementation NIMSessionViewController
- (void)viewDidLoad {
[super viewDidLoad];
//会话相关逻辑配置器安装
[self setupConfigurator];
}
- (void)setupConfigurator
{
_configurator = [[NIMSessionConfigurator alloc] init];
[_configurator setup:self];
}
@end
NIMSessionConfigurator 里面,
设置了聊天会话界面 NIMSessionViewController 的列表 TableView, 的 dataSource
@implementation NIMSessionConfigurator
- (void)setup:(NIMSessionViewController *)vc
{
vc.tableView.delegate = _tableAdapter;
vc.tableView.dataSource = _tableAdapter;
}
@end
我们看到的一行行聊天记录,自然是 dataSource
这样。两边就打通了