第一次使用环信,只是使用EaseUI简单的实现了客户与客服聊天的功能,后来加了需求,要实现发送轨迹,什么事轨迹?就是用户在浏览一件商品,然后点击客服,我们会自动将用户正在浏览的商品发送给客服,这就是轨迹,发送订单是一样的意思。为了实现这个功能,我浏览了环信的文档,结果只是在客服文档->多渠道集成->APP渠道集成中发现了发送轨迹的一些东西:
当APP用户浏览某个商品页时点击“联系客服”,APP可自动将该商品链接发送给客服。
要实现该功能,需在消息中增加扩展字段msgtype。
消息格式:
{ ext:{
msgtype:{
// 用户轨迹消息
track:{
// 消息标题
title: "我正在看:",
// 商品价格
price: "¥: 235.00",
// 商品描述
desc: "女装小香风气质蕾丝假两件短袖",
// 商品图片链接
img_url: "http://yourdomain.com/img/a.jpg",
// 商品页面链接
item_url: "http://yourdomain.com/item/a.html"
}
}
}
}
貌似文档里只有这个与轨迹沾边了,因为文档写的不具体,所以我去咨询了环信客服,客服告诉我需要使用拓展功能,在环信3.0文档->iOS客户端集成->消息 里
构造扩展消息
当 SDK 提供的消息类型不满足需求时,开发者可以通过扩展自 SDK 提供的文本、语音、图片、位置等消息类型,从而生成自己需要的消息类型。
这里是扩展自文本消息,如果这个自定义的消息需要用到语音或者图片等,可以扩展自语音、图片消息,亦或是位置消息。
// 以单聊消息举例
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要发送的消息"];
NSString *from = [[EMClient sharedClient] currentUsername];
//生成Message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeChat;// 设置为单聊消息
//message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
//message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息
message.ext = @{@"key":@"value"}; // 扩展消息部分
看到这,我刚明白了一些东西,需要把图1中的字典放到图2的message对象的ext属性下,图1的字典中的字段需要完全一样,写到这里,我以为就可以了,就可以发送轨迹了,但没有成功,代码如下,我是写在了viewDidLoad里了,这样一进来就可以发送了
- (void)sendOrder
{
NSDictionary *photoDict = self.model.photos[0];
NSDictionary *priceDict = self.model.price;
NSString *item_url = [NSString stringWithFormat:@"%@goods/%@", GOODSURL, self.model.goodsId];
NSDictionary *ext = @{@"msgtype":@{
//用户轨迹消息
@"track":@{
// 消息标题
@"title":@"我正在看:",
// 商品价格
@"price":[NSString stringWithFormat:@"%@ %@", priceDict[@"price"], ISSTRINGEMPTY(priceDict[@"currency"])],
// 商品描述
@"desc":self.model.name,
// 商品图片链接
@"img_url":photoDict[@"small"],
// 商品页面链接
@"item_url":item_url
}
}
};
EMMessage *message = [EaseSDKHelper sendTextMessage:@"order"
to:self.conversation.conversationId
messageType:EMChatTypeChat
messageExt:ext];
message.chatType = EMChatTypeChat;
message.ext = ext;
[self addMessageToDataSource:message progress:nil];
[[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {
if (!aError) {
// // 这个方法本来是写在EaseMessageViewController这个类的.m里的,我把接口写在了.h里,这样我们就可以调用了
[self _refreshAfterSentMessage:aMessage];
[self.tableView reloadData];
}else {
[[Hud sharedHud] hudtipApprearWithView:self.view Title:@"发送失败"];
[self.tableView reloadData];
}
}];
}
后来又咨询了环信客服,客服非常淡定的告诉我,UI需要自定义。。。瞬间一万个草泥马飘过啊,原来没有写好的,还需要自定义,没办法,继续开始查文档,后来看到了EaseUI的文档,发现了可以实现自定义Cell的方法:
实现自定义聊天样式
EaseMessageViewControllerDelegate
获取自定义消息 cell,根据 messageModel,用户自己判断是否显示自定义消息 cell。如果返回 nil 会显示默认;如果返回 cell 会显示用户自定义消息cell。
/*!
@method
@brief 获取消息自定义cell
@discussion 用户根据messageModel判断是否显示自定义cell。返回nil显示默认cell,否则显示用户自定义cell
@param tableView 当前消息视图的tableView
@param messageModel 消息模型
@result 返回用户自定义cell
*/
- (UITableViewCell *)messageViewController:(UITableView *)tableView
cellForMessageModel:(id)messageModel;
/*!
@method
@brief 获取消息cell高度
@discussion 用户根据messageModel判断,是否自定义显示cell的高度
@param viewController 当前消息视图
@param messageModel 消息模型
@param cellWidth 视图宽度
@result 返回用户自定义cell
*/
- (CGFloat)messageViewController:(EaseMessageViewController *)viewController
heightForMessageModel:(id)messageModel
withCellWidth:(CGFloat)cellWidth;
//具体创建自定义Cell的样例:
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)model
{
//样例为如果消息是文本消息显示用户自定义cell
if (model.bodyType == eMessageBodyType_Text) {
NSString *CellIdentifier = [CustomMessageCell cellIdentifierWithModel:model];
//CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell
CustomMessageCell *cell = (CustomMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.model = model;
return cell;
}
return nil;
}
- (CGFloat)messageViewController:(EaseMessageViewController *)viewController
heightForMessageModel:(id)messageModel
withCellWidth:(CGFloat)cellWidth
{
//样例为如果消息是文本消息使用用户自定义cell的高度
if (messageModel.bodyType == EMMessageBodyTypeText) {
//CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell
return [CustomMessageCell cellHeightWithModel:messageModel];
}
return 0.f;
}
ok,思路有了,开始照着这个文档写,自定义一个cell,继承于EaseBaseMessageCell,在自定义的.m里需要继承如下方法:
- (BOOL)isCustomBubbleView:(id)model
{
return YES;
}
- (void)setCustomBubbleView:(id)model
{
// 这里创建自定义的view
}
- (void)setCustomModel:(id)model
{
// 这里边给view赋值
}
- (void)updateCustomBubbleViewMargin:(UIEdgeInsets)bubbleMargin model:(id)mode
{
NSLog(@"-----哈哈 %@ %@", mode.message.ext, self.bubbleView.backgroundImageView);
}
+ (NSString *)cellIdentifierWithModel:(id)model
{
return @"CustomOrderCell";
}
+ (CGFloat)cellHeightWithModel:(id)model
{
return 120;
}
然后在我自定义的VC里写代理回调,我自定义的VC继承与EaseUI的EaseMessageViewController类
#pragma mark - EaseMessageViewControllerDelegate
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)messageModel
{
// 因为bodyType类型选择text类型就行了,所以我给text传了个order,用来判断当前我是否用我自己写的自定义的cell,DMCustomOrderTableViewCell是我自定义的cell
if (messageModel.bodyType == EMMessageBodyTypeText) {
if ([messageModel.text isEqualToString:@"order"]) {
NSString *CellIdentifier = [DMCustomOrderTableViewCell cellIdentifierWithModel:messageModel];
DMCustomOrderTableViewCell *cell = (DMCustomOrderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[DMCustomOrderTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:messageModel];
// 此处的delegate为EaseMessageCellDelegate,我们的vc需要代理它,用来实现点击这个自定义的cell实现跳转的功能
cell.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.model = messageModel;
return cell;
}else {
return nil;
}
}else {
return nil;
}
}
- (CGFloat)messageViewController:(EaseMessageViewController *)viewController heightForMessageModel:(id)messageModel withCellWidth:(CGFloat)cellWidth
{
if (messageModel.bodyType == EMMessageBodyTypeText) {
if ([messageModel.text isEqualToString:@"order"]) {
return [DMCustomOrderTableViewCell cellHeightWithModel:messageModel];
}else {
return 0.f;
}
}else {
return 0.f;
}
}
// 这个方法会由下面代码块里的messageCellSelected方法回调回来,然后跳转到商品详情,你也可以自定义需要跳转到哪里
- (BOOL)messageViewController:(EaseMessageViewController *)viewController didSelectMessageModel:(id)messageModel
{
if (messageModel.bodyType == EMMessageBodyTypeText) {
if ([messageModel.text isEqualToString:@"order"]) {
NSLog(@"商品链接 = %@", messageModel.message.ext[@"msgtype"][@"track"][@"item_url"]);
DMServiceDetailViewController *detailVC = [[DMServiceDetailViewController alloc] init];
detailVC.goodsDetailUrl = messageModel.message.ext[@"msgtype"][@"track"][@"item_url"];
[self.navigationController pushViewController:detailVC animated:YES];
return YES;
}else {
return NO;
}
}else {
return NO;
}
}
ok,这里基本上就实现了自定义的聊天cell显示出来的效果,下一步我们实现点击这个cell跳转的需求,上边的代码里我有写我们需要代理EaseMessageCellDelegate,实现如下方法:
#pragma mark - EaseMessageCellDelegate
// 这个方法会回调上边代码块里的- (BOOL)messageViewController:(EaseMessageViewController *)viewController didSelectMessageModel:(id)messageModel方法
- (void)messageCellSelected:(id)model
{
NSLog(@"---0.0 %@", model.message.ext);
if (model.bodyType == EMMessageBodyTypeText) {
if ([model.text isEqualToString:@"order"]) {
NSLog(@"商品链接 = %@", model.message.ext[@"msgtype"][@"track"][@"item_url"]);
if (self.delegate && [self.delegate respondsToSelector:@selector(messageViewController:didSelectMessageModel:)]) {
BOOL flag = [self.delegate messageViewController:self didSelectMessageModel:model];
if (flag) {
// 这个方法本来是写在EaseMessageViewController这个类的.m里的,我把接口写在了.h里,这样我们就可以调用了
[self _sendHasReadResponseForMessages:@[model.message] isRead:YES];
return;
}
}
}
}
}
- (void)statusButtonSelcted:(id)model withMessageCell:(EaseMessageCell*)messageCell
{
NSLog(@"+++0.0");
}
- (void)avatarViewSelcted:(id)model
{
NSLog(@"\\\\0.0");
}
ok,我们已经完成了环信自定义cell的东西,时间比较赶,没有太细致的走这个流程,我感觉我的代理回调还是有问题,我只不过走歪路给写出来了,还没细致看具体的流程应该怎么写,希望能够帮到各位,欢迎各位指教,谢谢!