云信IM在使用的过程中还是有蛮多的坑
1.离线消息云信只保存最近的100条 拉取历史消息时云信用的是本地的消息 如果App杀死进程时收到消息(离线消息)有可能丢失 在拉取消息时 应该换成拉取云端的消息 这样消息就可以完全的展示出来 但是在长按删除某一条数据时 只是删除本地的数据 在重新进入聊天页面下拉拉取时还会显示删除的消息(云信目前没有提供删除云端消息的接口 我给他们技术人员提了这个建议 当然他们没碉我 )
2.登陆问题 他们的登陆接口不能频繁调用 不然会出现登陆不成功的问题 云信接口返回错误吗 408 等等
3.在使用云信自带的UI控件时 如果需要在原来的基础上做修改时 首先你需要手动倒入他们的UI控件库 NIMKit 云信NIMKit下载地址
4.接下来讲解他们的控件及可以修改的地方:
NIMKitConfig 各个信息类型布局在 NIMKitConfig 中cell颜色背景 更多按钮下按钮的设置(照片,视频,拍摄等等)
#import "NIMKitConfig.h"
#import "NIMGlobalMacro.h"
#import "NIMMediaItem.h"
#import "UIImage+NIMKit.h"
#import
@interface NIMKitSettings()
{
BOOL _isRight;
}
- (instancetype)init:(BOOL)isRight;
@end
@implementation NIMKitConfig
- (instancetype) init
{
self = [super init];
if (self)
{
[self applyDefaultSettings];
//设置cell背景色
self.cellBackgroundColor = [UIColor clearColor];
}
return self;
}
- (NSArray *)defaultMediaItems
{
return @[[NIMMediaItem item:@"onTapCustomMediaItemPicture:"
normalImage:[UIImage nim_imageInKit:@"timing_photo"]
selectedImage:[UIImage nim_imageInKit:@"timing_photo_hight"]
title:@" 相册"],
[NIMMediaItem item:@"onTapMediaItemShowVideo:"
normalImage:[UIImage nim_imageInKit:@"timing_video"]
selectedImage:[UIImage nim_imageInKit:@"timing_video_hight"]
title:@" 视频"],
[NIMMediaItem item:@"onTapMediaItemShoot:"
normalImage:[UIImage nim_imageInKit:@"timing_camera"]
selectedImage:[UIImage nim_imageInKit:@"timing_camera_hight"]
title:@" 拍摄"],
//多加几个使布局经凑
[NIMMediaItem item:@"empty:"
normalImage:nil
selectedImage:nil
title:@""],
[NIMMediaItem item:@"empty:"
normalImage:nil
selectedImage:nil
title:nil],
];
}
- (CGFloat)maxNotificationTipPadding{
return 20.f;
}
- (void)applyDefaultSettings
{
_inputMaxLength = 1000; //输入框最大输入数
_messageInterval = 300;
_messageLimit = 20;
_recordMaxDuration = 60.f; //录音的最大时长
_placeholder = @"请输入内容";
_nickFont = [UIFont systemFontOfSize:13.0];
_nickColor = SharedColor.textLightBlack;
_receiptFont = [UIFont systemFontOfSize:13.0];
_receiptColor = SharedColor.textLightBlack;
_avatarType = NIMKitAvatarTypeRounded;
_leftBubbleSettings = [[NIMKitSettings alloc] init:NO];
_rightBubbleSettings = [[NIMKitSettings alloc] init:YES];
}
- (NIMKitSetting *)setting:(NIMMessage *)message
{
NIMKitSettings *settings = message.isOutgoingMsg? self.rightBubbleSettings : self.leftBubbleSettings;
switch (message.messageType) {
case NIMMessageTypeText:
return settings.textSetting;
case NIMMessageTypeImage:
return settings.imageSetting;
case NIMMessageTypeLocation:
return settings.locationSetting;
case NIMMessageTypeAudio:
return settings.audioSetting;
case NIMMessageTypeVideo:
return settings.videoSetting;
case NIMMessageTypeFile:
return settings.fileSetting;
case NIMMessageTypeTip:
return settings.tipSetting;
case NIMMessageTypeRobot:
return settings.robotSetting;
case NIMMessageTypeNotification:
{
NIMNotificationObject *object = (NIMNotificationObject *)message.messageObject;
switch (object.notificationType)
{
case NIMNotificationTypeTeam:
return settings.teamNotificationSetting;
case NIMNotificationTypeChatroom:
return settings.chatroomNotificationSetting;
case NIMNotificationTypeNetCall:
return settings.netcallNotificationSetting;
default:
break;
}
break;
}
default:
break;
}
return settings.unsupportSetting;
}
@end
@implementation NIMKitSettings
- (instancetype)init:(BOOL)isRight
{
self = [super init];
if (self)
{
_isRight = isRight;
[self applyDefaultSettings];
}
return self;
}
- (void)applyDefaultSettings
{
[self applyDefaultTextSettings];
[self applyDefaultAudioSettings];
[self applyDefaultVideoSettings];
[self applyDefaultFileSettings];
[self applyDefaultImageSettings];
[self applyDefaultLocationSettings];
[self applyDefaultTipSettings];
[self applyDefaultRobotSettings];
[self applyDefaultUnsupportSettings];
[self applyDefaultTeamNotificationSettings];
[self applyDefaultChatroomNotificationSettings];
[self applyDefaultNetcallNotificationSettings];
}
#pragma mark -文本
- (void)applyDefaultTextSettings
{
_textSetting = [[NIMKitSetting alloc] init:_isRight];
_textSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{11,11,9,11}") : UIEdgeInsetsFromString(@"{11,15,9,9}");
_textSetting.textColor = _isRight? NIMKit_UIColorFromRGB(0x000000) : NIMKit_UIColorFromRGB(0x000000);
_textSetting.font = [UIFont systemFontOfSize:16];
_textSetting.showAvatar = YES;
}
#pragma mark -视频
- (void)applyDefaultVideoSettings
{
_videoSetting = [[NIMKitSetting alloc] init:_isRight];
_videoSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{3,3,3,3}") : UIEdgeInsetsFromString(@"{3,3,3,3}");
_videoSetting.font = [UIFont systemFontOfSize:15];
_videoSetting.showAvatar = YES;
}
#pragma mark -图片
- (void)applyDefaultImageSettings
{
_imageSetting = [[NIMKitSetting alloc] init:_isRight];
_imageSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{3,3,3,3}") : UIEdgeInsetsFromString(@"{3,3,3,3}");
_imageSetting.showAvatar = YES;
}
#pragma mark -语音
- (void)applyDefaultAudioSettings
{
_audioSetting = [[NIMKitSetting alloc] init:_isRight];
_audioSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{8,12,9,14}") : UIEdgeInsetsFromString(@"{8,13,9,12}");
_audioSetting.textColor = _isRight? NIMKit_UIColorFromRGB(0x000000) : NIMKit_UIColorFromRGB(0x000000);
_audioSetting.font = [UIFont systemFontOfSize:15];
_audioSetting.showAvatar = YES;
}
#pragma mark -群通知消息
- (void)applyDefaultTeamNotificationSettings
{
_teamNotificationSetting = [[NIMKitSetting alloc] init:_isRight];
_teamNotificationSetting.contentInsets = UIEdgeInsetsZero;
_teamNotificationSetting.textColor = SharedColor.textLightBlack;
_teamNotificationSetting.font = [UIFont systemFontOfSize:13];
_teamNotificationSetting.showAvatar = NO;
// UIImage *backgroundImage = [[UIImage nim_imageInKit:@"icon_session_time_bg"] resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{8,20,8,20}") resizingMode:UIImageResizingModeStretch];
// _teamNotificationSetting.normalBackgroundImage = backgroundImage;
// _teamNotificationSetting.highLightBackgroundImage = backgroundImage;
}
- (void)applyDefaultFileSettings
{
_fileSetting = [[NIMKitSetting alloc] init:_isRight];
_fileSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{3,3,3,8}") : UIEdgeInsetsFromString(@"{3,8,3,3}");
_fileSetting.font = [UIFont systemFontOfSize:13];
_fileSetting.showAvatar = YES;
}
- (void)applyDefaultLocationSettings
{
_locationSetting = [[NIMKitSetting alloc] init:_isRight];
_locationSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{3,3,3,8}") : UIEdgeInsetsFromString(@"{3,8,3,3}");
_locationSetting.textColor = SharedColor.textLightBlack;
_locationSetting.font = [UIFont systemFontOfSize:13];
_locationSetting.showAvatar = YES;
}
- (void)applyDefaultTipSettings
{
_tipSetting = [[NIMKitSetting alloc] init:_isRight];
_tipSetting.contentInsets = UIEdgeInsetsZero;
_tipSetting.textColor = SharedColor.textLightBlack;
_tipSetting.font = [UIFont systemFontOfSize:13.f];
_tipSetting.showAvatar = NO;
// UIImage *backgroundImage = [[UIImage nim_imageInKit:@""] resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{8,20,8,20}") resizingMode:UIImageResizingModeStretch];;
// _tipSetting.normalBackgroundImage = backgroundImage;
// _tipSetting.highLightBackgroundImage = backgroundImage;
}
- (void)applyDefaultRobotSettings
{
_robotSetting = [[NIMKitSetting alloc] init:_isRight];
_robotSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{11,11,9,15}") : UIEdgeInsetsFromString(@"{11,15,9,9}");
_robotSetting.textColor = _isRight? SharedColor.textLightBlack : SharedColor.textLightBlack;
_robotSetting.font = [UIFont systemFontOfSize:14];
// _robotSetting.showAvatar = YES;
}
- (void)applyDefaultUnsupportSettings
{
_unsupportSetting = [[NIMKitSetting alloc] init:_isRight];
_unsupportSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{11,11,9,15}") : UIEdgeInsetsFromString(@"{11,15,9,9}");
_unsupportSetting.textColor = _isRight? SharedColor.textLightBlack : SharedColor.textLightBlack;
_unsupportSetting.font = [UIFont systemFontOfSize:13];
_unsupportSetting.showAvatar = YES;
}
- (void)applyDefaultChatroomNotificationSettings
{
_chatroomNotificationSetting = [[NIMKitSetting alloc] init:_isRight];
_chatroomNotificationSetting.contentInsets = UIEdgeInsetsZero;
_chatroomNotificationSetting.textColor = SharedColor.textLightBlack;
_chatroomNotificationSetting.font = [UIFont systemFontOfSize:13];
_chatroomNotificationSetting.showAvatar = NO;
UIImage *backgroundImage = [[UIImage nim_imageInKit:@"icon_session_time_bg"] resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{8,20,8,20}") resizingMode:UIImageResizingModeStretch];
_chatroomNotificationSetting.normalBackgroundImage = backgroundImage;
_chatroomNotificationSetting.highLightBackgroundImage = backgroundImage;
}
- (void)applyDefaultNetcallNotificationSettings
{
_netcallNotificationSetting = [[NIMKitSetting alloc] init:_isRight];
_netcallNotificationSetting.contentInsets = _isRight? UIEdgeInsetsFromString(@"{11,11,9,15}") : UIEdgeInsetsFromString(@"{11,15,9,9}");
_netcallNotificationSetting.textColor = _isRight? SharedColor.textLightBlack : SharedColor.textLightBlack;
_netcallNotificationSetting.font = [UIFont systemFontOfSize:13];
_netcallNotificationSetting.showAvatar = YES;
}
@end
NIMSessionViewController 聊天回话页面的父类控制器
NIMKitTitleView 导航了标题View
NIMSessionTimestampCell 时间显示的cell
NIMMessageCell 聊天信息展示的cell
NIMSessionNotificationContentView 群消息提醒展示的contentView
NIMSessionTextContentView 文本展示的contentView
NIMInputView 聊天页面下的输入框
NIMInputToolBar 输入框上的语音 表情 更多按钮显示的地方
NIMCellLayoutConfig cell布局的协议
页面的布局 控制
#import "NIMCellLayoutConfig.h"
#import "NIMSessionMessageContentView.h"
#import "NIMSessionUnknowContentView.h"
#import "M80AttributedLabel+NIMKit.h"
#import "NIMKitUtil.h"
#import "UIImage+NIMKit.h"
#import "NIMMessageModel.h"
#import "NIMBaseSessionContentConfig.h"
#import "NIMKit.h"
@interface NIMCellLayoutConfig()
@end
@implementation NIMCellLayoutConfig
- (CGSize)contentSize:(NIMMessageModel *)model cellWidth:(CGFloat)cellWidth{
idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];
return [config contentSize:cellWidth message:model.message];
}
- (NSString *)cellContent:(NIMMessageModel *)model{
idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];
NSString *cellContent = [config cellContent:model.message];
return cellContent.length ? cellContent : @"NIMSessionUnknowContentView";
}
- (UIEdgeInsets)contentViewInsets:(NIMMessageModel *)model{
idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];
return [config contentViewInsets:model.message];
}
- (UIEdgeInsets)cellInsets:(NIMMessageModel *)model
{
if ([[self cellContent:model] isEqualToString:@"NIMSessionNotificationContentView"]) {
return UIEdgeInsetsZero;
}
CGFloat cellTopToBubbleTop = 3;
CGFloat otherNickNameHeight = 20;
CGFloat otherBubbleOriginX = [self shouldShowAvatar:model]? 55 : 0;
CGFloat cellBubbleButtomToCellButtom = 13;
if ([self shouldShowNickName:model])
{
//要显示名字
return UIEdgeInsetsMake(cellTopToBubbleTop + otherNickNameHeight ,otherBubbleOriginX,cellBubbleButtomToCellButtom, 0);
}
else
{
return UIEdgeInsetsMake(cellTopToBubbleTop,otherBubbleOriginX,cellBubbleButtomToCellButtom, 0);
}
}
- (BOOL)shouldShowAvatar:(NIMMessageModel *)model
{
return [[NIMKit sharedKit].config setting:model.message].showAvatar;
}
- (BOOL)shouldShowNickName:(NIMMessageModel *)model{
NIMMessage *message = model.message;
if (message.messageType == NIMMessageTypeNotification)
{
NIMNotificationType type = [(NIMNotificationObject *)message.messageObject notificationType];
if (type == NIMNotificationTypeTeam) {
return NO;
}
}
if (message.messageType == NIMMessageTypeTip) {
return NO;
}
return (!message.isOutgoingMsg && message.session.sessionType == NIMSessionTypeTeam);
}
- (BOOL)shouldShowLeft:(NIMMessageModel *)model
{
return !model.message.isOutgoingMsg;
}
- (CGPoint)avatarMargin:(NIMMessageModel *)model
{
return CGPointMake(8.f, 0.f);
}
- (CGSize)avatarSize:(NIMMessageModel *)model
{
return CGSizeMake(42, 42);
}
- (CGPoint)nickNameMargin:(NIMMessageModel *)model
{
return [self shouldShowAvatar:model] ? CGPointMake(57.f, -3.f) : CGPointMake(10.f, -3.f);
}
- (NSArray *)customViews:(NIMMessageModel *)model
{
return nil;
}
- (BOOL)disableRetryButton:(NIMMessageModel *)model
{
if (!model.message.isReceivedMsg)
{
return model.message.deliveryState != NIMMessageDeliveryStateFailed;
}
else
{
return model.message.attachmentDownloadState != NIMMessageAttachmentDownloadStateFailed;
}
}
@end
NIMInputAudioRecordIndicatorView 录音提示View
NIMSessionMsgDatasource 云信下拉改为请求云记录消息
在 NIMSessionMsgDatasource.m 中做修改 云信下拉改为请求云记录消息
#pragma mark - answer 在此修改
- (void)loadHistoryMessagesWithComplete:(void(^)(NSInteger index, NSArray *messages , NSError *error))handler{
__block NIMMessageModel *currentOldestMsg = nil;
[self.items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[NIMMessageModel class]]) {
currentOldestMsg = (NIMMessageModel*)obj;
*stop = YES;
}
}];
__block NSInteger index = 0;
if ([self.dataProvider respondsToSelector:@selector(pullDown:handler:)])
{
__weak typeof(self) wself = self;
[self.dataProvider pullDown:currentOldestMsg.message handler:^(NSError *error, NSArray *messages) {
NIMKit_Dispatch_Async_Main(^{
NSInteger index = [wself insertMessages:messages];
if (handler) {
handler(index,messages,error);
}
});
}];
return;
}else{
#warning 在此修改
NIMHistoryMessageSearchOption *searchOpt = [[NIMHistoryMessageSearchOption alloc] init];
searchOpt.startTime = 0;
searchOpt.endTime = currentOldestMsg.message.timestamp;
searchOpt.currentMessage = currentOldestMsg.message;
searchOpt.limit = self.messageLimit;
searchOpt.sync = YES;
[[NIMSDK sharedSDK].conversationManager fetchMessageHistory:_currentSession option:searchOpt result:^(NSError *error, NSArray *messages) {
if (!error) {
NSArray *array = [messages sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
NIMMessage *hm1 = (NIMMessage *)obj1;
NIMMessage *hm2 = (NIMMessage *)obj2;
if (hm1.timestamp > hm2.timestamp) {
return NSOrderedDescending;
}else {
return NSOrderedAscending;
}
}];
index = [self insertMessages:array];
if (handler) {
NIMKit_Dispatch_Async_Main(^{
handler(index,messages,nil);
[self postNotification:@"loadHistoryMessages"];
});
}
}
}];
// NSArray *messages = [[[NIMSDK sharedSDK] conversationManager] messagesInSession:_currentSession
// message:currentOldestMsg.message
// limit:self.messageLimit];
// index = [self insertMessages:messages];
// if (handler) {
// NIMKit_Dispatch_Async_Main(^{
// handler(index,messages,nil);
// });
// }
}
}
5.接下来重点来 自定义消息 以及自定义消息布局
首先在AppDelegate中 注册
//自定义消息布局
[[NIMKit sharedKit] registerLayoutConfig:[TimingCellLayoutConfig new]];
//自定义消息对象序列化
[NIMCustomObject registerCustomDecoder:[[TimingCustomAttachmentDecoder alloc] init]];
TimingCustomAttachmentDecoder自定义消息解析器
#import "TimingCustomAttachmentDecoder.h"
#import "TimingCustomAttachmentDefines.h"
#import "TCustomInvitedIntoTeamAttachment.h"
#import "TimingCustomAttachment.h"
@implementation TimingCustomAttachmentDecoder
- (id)decodeAttachment:(NSString *)content
{
id attachment = nil;
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
if (data) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
if ([dict isKindOfClass:[NSDictionary class]])
{
NSInteger type = [dict jsonInteger:TimingType];
switch (type) {
case CustomMessageTypeInvitedIntoTeam:{//邀请进群
attachment = [[TCustomInvitedIntoTeamAttachment alloc] init];
((TCustomInvitedIntoTeamAttachment *)attachment).type = [dict jsonInteger:@"type"];
((TCustomInvitedIntoTeamAttachment *)attachment).titleStr = [dict jsonString:@"titleStr"];
((TCustomInvitedIntoTeamAttachment *)attachment).teamType = [dict jsonInteger:@"teamType"];
((TCustomInvitedIntoTeamAttachment *)attachment).contentStr = [dict jsonString:@"contentStr"];
((TCustomInvitedIntoTeamAttachment *)attachment).imageUrl = [dict jsonString:@"imageUrl"];
((TCustomInvitedIntoTeamAttachment *)attachment).groupID = [dict jsonInteger:@"groupID"];
((TCustomInvitedIntoTeamAttachment *)attachment).teamID = [dict jsonString:@"teamID"];
}
break;
}
}
}
return attachment;
}
@end
ifndef TimingCustomAttachmentDefines_h
#define TimingCustomAttachmentDefines_h
typedef NS_ENUM(NSInteger,TimingCustomMessageType){
CustomMessageTypeImageAndTitle = 1,//图片和文字一起
CustomMessageTypeInvitedIntoTeam = 2,//邀请进群
};
#define TimingType @"type"
//手势点击方法
#define TimingCustomImageAndTitleTouch @"TimingCustomImageAndTitleTouch"
#define CustomImageAndTitleTapTitleLablel @"TapTitleLablel"
#define CustomImageAndTitleTapSubTitleLablel @"TapSubTitleLablel"
#define TimingCustomInviteGroupTouch @"TimingCustomInviteGroupTouch"
#endif /* TimingCustomAttachmentDefines_h */
自定义消息的模型类 TCustomInvitedIntoTeamAttachment
TCustomInvitedIntoTeamAttachment.h
#import
#import "TimingCustomAttachmentDefines.h"
//邀请进群的自定义消息
@interface TCustomInvitedIntoTeamAttachment : NSObject
@property (nonatomic,copy) NSString *titleStr;
@property (nonatomic,assign)NSInteger teamType;
@property (nonatomic,copy) NSString *contentStr;
@property(nonatomic,copy) NSString *imageUrl;
@property (nonatomic,assign)NSInteger groupID;
@property(nonatomic,copy) NSString *teamID;
@property (nonatomic,assign)NSInteger type;
-(NIMMessage *)assembleMessage;
@end
TCustomInvitedIntoTeamAttachment.m
#import "TCustomInvitedIntoTeamAttachment.h"
@implementation TCustomInvitedIntoTeamAttachment
- (NSString *)encodeAttachment
{
NSDictionary *dict = @{
TimingType:@(CustomMessageTypeInvitedIntoTeam),
@"titleStr":self.titleStr?self.titleStr:@"",
@"teamType" :@(self.teamType),
@"contentStr":self.contentStr?self.contentStr:@"",
@"imageUrl":self.imageUrl?self.imageUrl:@"",
@"groupID":self.groupID?@(self.groupID):@"",
@"teamID":self.teamID?self.teamID:@"",
};
NSData *data = [NSJSONSerialization dataWithJSONObject:dict
options:0
error:nil];
NSString *content = nil;
if (data) {
content = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
}
return content;
}
#pragma mark -拼装消息
-(NIMMessage *)assembleMessage{
NIMCustomObject *object = [[NIMCustomObject alloc] init];
object.attachment = self;
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
setting.apnsEnabled = YES;
setting.shouldBeCounted = YES;
message.setting = setting;
//用messageObject判断不了 直接用apnsPayload字典
NSDictionary *dict = @{
TimingType:@(CustomMessageTypeInvitedIntoTeam),
@"titleStr":self.titleStr?self.titleStr:@"",
@"teamType" :@(self.teamType),
@"contentStr":self.contentStr?self.contentStr:@"",
@"imageUrl":self.imageUrl?self.imageUrl:@"",
@"groupID":@(self.groupID),
@"teamID":self.teamID?self.teamID:@"",
};
message.apnsPayload = dict;
return message;
}
@end
自定义消息的View
NIMSessionMessageContentView.h
#import "NIMSessionMessageContentView.h"
#import "TCustomInvitedIntoTeamAttachment.h"
@interface TCustomInvitedIntoTeamContentView : NIMSessionMessageContentView
@property (nonatomic, strong) UILabel *lblTitle;//标题
@property (nonatomic, strong) UIImageView *ivType;//群类型
@property (nonatomic, strong) UILabel *lblContent;//内容
@property (nonatomic, strong) UIImageView *ivTeam;//群图像
@property (nonatomic, strong) TCustomInvitedIntoTeamAttachment *attachment;
@end
NIMSessionMessageContentView.m
#import "TCustomInvitedIntoTeamContentView.h"
#import "UIView+NIM.h"
#import "TimingCustomAttachmentDefines.h"
@implementation TCustomInvitedIntoTeamContentView
{
UILabel *_lblname;
UIView *_viewBack;
}
- (instancetype)initSessionMessageContentView{
self = [super initSessionMessageContentView];
if (self) {
[self setUpView];
}
return self;
}
-(void)setUpView{
_lblname = [UILabel new];
[self addSubview:_lblname];
_lblname.textColor = [UIColor blackColor];
_lblname.font = [UIFont systemFontOfSize:16];
[_lblname mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(15);
make.leading.equalTo(self).offset(12);
make.width.equalTo(@222);
make.height.equalTo(@14);
}];
_viewBack = [UIView new];
_viewBack.clipsToBounds = YES;
_viewBack.layer.cornerRadius = 5;
_viewBack.backgroundColor = [UIColor whiteColor];
_viewBack.layer.borderWidth = 0.5;
_viewBack.userInteractionEnabled = NO;
[self addSubview:_viewBack];
[_viewBack mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@58);
make.leading.equalTo(self).offset(12);
make.trailing.equalTo(self).offset(-20);
make.bottom.equalTo(self).offset(-18);
}];
//群成员图像
_ivTeam = [UIImageView new];
_ivTeam.clipsToBounds = YES;
_ivTeam.layer.cornerRadius = 5;
[_viewBack addSubview:_ivTeam];
[_ivTeam mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.equalTo(@30);
make.centerY.equalTo(_viewBack.mas_centerY);
make.trailing.equalTo(_viewBack).offset(-10);
}];
//标题
_lblTitle = [UILabel new];
[_viewBack addSubview:_lblTitle];
_lblTitle.textColor = [UIColor blackColor];
_lblTitle.font = [UIFont systemFontOfSize:15];
[_lblTitle mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_viewBack).offset(12);
make.leading.equalTo(_viewBack).offset(10);
make.width.mas_lessThanOrEqualTo(@120);
make.height.equalTo(@13);
}];
//群类型
_ivType = [UIImageView new];
[_viewBack addSubview:_ivType];
[_ivType mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(_lblTitle.mas_centerY);
make.leading.equalTo(_lblTitle.mas_trailing).offset(5);
make.height.equalTo(@17);
make.width.equalTo(@35);
}];
//信息内容
_lblContent = [UILabel new];
[_viewBack addSubview:_lblContent];
_lblContent.textColor = SharedColor.textLightBlack;
_lblContent.font = [UIFont systemFontOfSize:14];
[_lblContent mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_lblTitle.mas_bottom).offset(8);
make.leading.equalTo(_viewBack).offset(10);
make.width.equalTo(@158);
}];
}
- (void)refresh:(NIMMessageModel*)data{
//务必调用super方法
[super refresh:data];
NIMCustomObject *object = (NIMCustomObject *)data.message.messageObject;
TCustomInvitedIntoTeamAttachment *attachment = (TCustomInvitedIntoTeamAttachment *)object.attachment;
_attachment = attachment;
self.lblTitle.text = attachment.titleStr;
switch (attachment.teamType) {
case 1:{
[self.ivType setImage:[UIImage imageNamed:@"team_share_normal"]];
}
break;
case 2:{
[self.ivType setImage:[UIImage imageNamed:@"team_share_clock"]];
}
break;
case 3:{
[self.ivType setImage:[UIImage imageNamed:@"team_share_delegate"]];
}
break;
default:
break;
}
self.lblContent.text = attachment.contentStr;
[self.ivTeam yy_setImageWithURL:[NSURL URLWithString:attachment.imageUrl] placeholder:[UIImage imageNamed:@"user_bg_icon"]];
NIMMessage *message = data.message;
if (message.isOutgoingMsg) {
_lblname.text = @"邀请道友入群";
[_lblname mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(15);
make.leading.equalTo(self).offset(12);
make.width.equalTo(@222);
make.height.equalTo(@14);
}];
[_viewBack mas_remakeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@58);
make.leading.equalTo(self).offset(12);
make.trailing.equalTo(self).offset(-20);
make.bottom.equalTo(self).offset(-18);
}];
_viewBack.layer.borderColor = [UIColor whiteColor].CGColor;
}else{
_viewBack.layer.borderColor = TIMINGCOLOR(234, 228, 222, 1).CGColor;
_lblname.text = @"邀请你入群";
[_lblname mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(15);
make.leading.equalTo(self).offset(15);
make.width.equalTo(@222);
make.height.equalTo(@14);
}];
[_viewBack mas_remakeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(@58);
make.leading.equalTo(self).offset(15);
make.trailing.equalTo(self).offset(-16);
make.bottom.equalTo(self).offset(-18);
}];
}
}
#pragma mark - 气泡
- (UIImage *)chatBubbleImageForState:(UIControlState)state outgoing:(BOOL)outgoing
{
NIMKitSetting *setting = [[NIMKit sharedKit].config setting:self.model.message];
if (state == UIControlStateNormal)
{
return setting.normalBackgroundImage;
}
else
{
return setting.highLightBackgroundImage;
}
}
/**
* 手指从contentView内部抬起
*/
- (void)onTouchUpInside:(id)sender
{
NIMKitEvent *event = [[NIMKitEvent alloc] init];
event.eventName = TimingCustomInviteGroupTouch;
event.messageModel = self.model;
event.attachment = _attachment;
[self.delegate onCatchEvent:event];
}
/**
* 手指从contentView外部抬起
*/
- (void)onTouchUpOutside:(id)sender{
[super onTouchUpOutside:sender];
}
/**
* 手指按下contentView
*/
- (void)onTouchDown:(id)sender{
[super onTouchDown:sender];
}
@end
在实现自定义消息布局的协议 NIMCellLayoutConfig
NIMCellLayoutConfig.h
#import "NIMCellLayoutConfig.h"
@interface TimingCellLayoutConfig : NIMCellLayoutConfig
@end
NIMCellLayoutConfig.m
#import "TimingCellLayoutConfig.h"
#import "TimingCustomAttachment.h"
#import "TCustomInvitedIntoTeamAttachment.h"
@implementation TimingCellLayoutConfig
#pragma mark -构造的cellContent类名
- (NSString *)cellContent:(NIMMessageModel *)model{
NIMMessage *message = model.message;
//填入contentView类型
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
return @"TCustomInvitedIntoTeamContentView";
}
}
//如果不是自己定义的消息,就走内置处理流程
return [super cellContent:model];
}
#pragma mark -返回message的内容大小
- (CGSize)contentSize:(NIMMessageModel *)model cellWidth:(CGFloat)width{
NIMMessage *message = model.message;
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
return CGSizeMake(251.5, 120);
}
}
//如果不是自己定义的消息,就走内置处理流程
return [super contentSize:model cellWidth:width];
}
#pragma mark - cell气泡距离整个cell的内间距
- (UIEdgeInsets)cellInsets:(NIMMessageModel *)model{
NIMMessage *message = model.message;
//填入气泡距cell的边距,选填
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
if (model.message.isOutgoingMsg) {
return UIEdgeInsetsMake(25, 10, 22, 75);
}else{
//有昵称是距上30
return UIEdgeInsetsMake(25, 60, 22, 10);
}
}
}
//如果不是自己定义的消息,就走内置处理流程
return [super cellInsets:model];
}
#pragma mark - ContentView内容 距离气泡的内间距
- (UIEdgeInsets)contentViewInsets:(NIMMessageModel *)model{
NIMMessage *message = model.message;
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
return UIEdgeInsetsMake(0, 0, 0, 0);
}
}
//如果不是自己定义的消息,就走内置处理流程
return [super contentViewInsets:model];
}
#pragma mark -昵称的位置
- (CGPoint)nickNameMargin:(NIMMessageModel *)model{
// NIMMessage *message = model.message;
//
// if (message.messageType == NIMMessageTypeCustom) {
// NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//
// //邀请入群
// if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
//
// if (model.message.isOutgoingMsg) {
//
// return CGPointMake(30.f, 0.f);
//
// }else{
//
// //有昵称是距上
// return CGPointMake(60.f, 0.f);
// }
// }
//
// }
return [super nickNameMargin:model];
}
#pragma mark-是否取消重试按钮
- (BOOL)disableRetryButton:(NIMMessageModel *)model
{
NIMMessage *message = model.message;
//填入contentView类型
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]]) {
return YES;
}
}
return [super disableRetryButton:model];
}
- (NSArray *)customViews:(NIMMessageModel *)model
{
return [super customViews:model];
}
#pragma mark -是否展示图像
- (BOOL)shouldShowAvatar:(NIMMessageModel *)model
{
return [super shouldShowAvatar:model];
}
#pragma mark -是否展示昵称
- (BOOL)shouldShowNickName:(NIMMessageModel *)model{
NIMMessage *message = model.message;
//填入contentView类型
if (message.messageType == NIMMessageTypeCustom) {
NIMCustomObject *object = (NIMCustomObject *)message.messageObject;
//邀请入群
if ([object.attachment isKindOfClass:[TCustomInvitedIntoTeamAttachment class]] && (message.session.sessionType == NIMSessionTypeTeam)) {
return YES;
}
}
if (message.session.sessionType == NIMSessionTypeTeam) {
return YES;
}
return [super shouldShowNickName:model];
}
@end
自定义消息效果图:
IMG_4452.PNG
图片发自简书App
图片发自简书App
图片发自简书App
读者如有疑问可以给博主留言 或者加QQ 1256454781 随便点个赞呗 谢谢
顺便分享一下云信内部技术文档 http://faq.netease.im/#KB0014