iOS開發(fā)集成騰訊云IM即時通訊

最近做的項目里公司說明確要用騰訊云的IM,傳送門:https://cloud.tencent.com/product/im?fromSource=gwzcw.471467.471467.471467但两,剛開始集成會發(fā)現(xiàn)有很多坑點,下面讓我們一步一步來集成:
首先 podfile加入:

pod 'TXIMSDK_iOS'

pod install一下就會發(fā)現(xiàn) 騰訊云的通訊基礎(chǔ)SDK已經(jīng)被引入進來了频鉴,可以進行socket連接互相發(fā)送消息了销斟,但是UI框架是沒有的祭玉,所以還是得去下載他的demo去研究一波箱熬,
馁害,將下面這個TUIKit工程拖入項目文件目錄下:


屏幕快照 2019-03-23 下午5.07.12.png

首先選擇TUIKit的target編譯一波窄俏,然后退出Xcode,然后再編譯一波自己的工程target碘菜,如果不報錯凹蜈,那就可以集成進去了,注意忍啸,這里如果報錯的話仰坦,幾乎都是framework路徑設(shè)置引用問題,自己直接去search path設(shè)置那里面看就行计雌。
通常做IM最核心的東西人家已經(jīng)給我們做好了悄晃,接下來就是自定義氣泡消息了,這里得看懂他代碼是怎么寫的白粉,進去你會發(fā)現(xiàn)有幾個基類的類:我們要做的就是重寫那幾個基類就行:

公司職位信息氣泡:CompanyInfoCell.h:

#import <UIKit/UIKit.h>
#import "TMessageCell.h"
#import "JobCell.h"
#import "JobModel.h"

@protocol companyInfoDelegate <NSObject>

- (void)companyInfoClickedWithContent:(JobModel *)model;


@end
NS_ASSUME_NONNULL_BEGIN

@interface CompanyInfoCellData :TMessageCellData

@property (nonatomic,strong)NSString *totalContent;

@end
@interface CompanyInfoCell : TMessageCell

@property (nonatomic, strong) UIView *containerView;

@property (nonatomic,strong)JobCell *jobCell;

@property(nonatomic,weak) id <companyInfoDelegate> companyInfoDelegate;


+ (NSString *)cellIdentifier;


@end

NS_ASSUME_NONNULL_END

CompanyInfoCell.m:

#import "CompanyInfoCell.h"
#import <TUIKit.h>
#import <THeader.h>
@implementation CompanyInfoCellData



@end

@interface CompanyInfoCell () {
    
}

@end
@implementation CompanyInfoCell

- (CGFloat)getHeight:(CompanyInfoCellData *)data;
{
    return 200;
}


- (void)setData:(CompanyInfoCellData *)data;
{
    //update layout
    _containerView.frame = CGRectMake(25, TMessageCell_Padding, Screen_Width -50, 180);
    _jobCell.frame = _containerView.bounds;
    [_containerView layoutSubviews];
    // MARK: - setCellWithData
    JobModel *model = [JobModel  new];
    NSDictionary *json  = [data.totalContent mj_JSONObject];
    NSDictionary *bodyJson = [[json objectForKey:kMessageBody] mj_JSONObject];
//    [_jobCell setCellWithData:[JobModel mj_objectWithKeyValues:bodyJson]];
    [_jobCell setPostion:[CompanyInFoDataModel mj_objectWithKeyValues:bodyJson]];
}

- (void)setupViews {
    self.backgroundColor = [UIColor clearColor];
    
    _containerView = [[UIView alloc] init];
    _containerView.backgroundColor = [UIColor whiteColor];
    _containerView.layer.borderColor = [UIColor grayColor].CGColor;
    _containerView.layer.cornerRadius = 5.0;
    [_containerView.layer setMasksToBounds:YES];
    [self addSubview:_containerView];
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    _jobCell = [[JobCell alloc] initWithStyle:0 reuseIdentifier:NSStringFromClass([JobCell class])];
    [_containerView addSubview:_jobCell];
   UITapGestureRecognizer *tap =  [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(buttonAction:)];
    [_containerView addGestureRecognizer: tap];
}

// MARK: - private Method
- (void)buttonAction:(id)sender {
    if (_companyInfoDelegate &&[_companyInfoDelegate respondsToSelector:@selector(companyInfoClickedWithContent:)]) {
        [_companyInfoDelegate companyInfoClickedWithContent:_jobCell.model];
    }
}


+ (NSString *)cellIdentifier {
    return NSStringFromClass([self class]);
}

CompanyInFoDataModel.h:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface CompanyInFoDataModel : NSObject

/*
 
 {"degreeRequirement":"博士",
 "enterpriseName":"深圳市xxxxx公司",
 "expectJobCity":"101280600",
 "experienceRequirement":"10年以上",
 "financingStage":"天使輪",
 "headPortrait":"http://.oss-cn-hangzhou.aliyuncs.com/S8PeJn_%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190320174739.jpg",
 "launchCommunicativeTimeStamp":1553326495,
 "nickname":"蘇海峰",
 "positionName":"前端開發(fā)",
 "salaryHighestRequirement":2000.00,
 "salaryMinimumRequirement":1000.00,
 "synopsis":"由你發(fā)起的溝通",
 "workDetailedAddress":"深圳市路通網(wǎng)絡(luò)技術(shù)有限公司"}
 */

@property (nonatomic,strong)NSString *degreeRequirement;

@property (nonatomic,strong)NSString *enterpriseName;

@property (nonatomic,strong)NSString *financingStage;

@property (nonatomic,strong)NSString *expectJobCity;

@property (nonatomic,strong)NSString *experienceRequirement;

@property (nonatomic,strong)NSString *headPortrait;

@property (nonatomic,assign)NSInteger launchCommunicativeTimeStamp;

@property (nonatomic,strong)NSString *nickname;

@property (nonatomic,strong)NSString *positionName;

@property (nonatomic,strong)NSString *salaryHighestRequirement;

@property (nonatomic,strong)NSString *salaryMinimumRequirement;

@property (nonatomic,strong)NSString *synopsis;

@property (nonatomic,strong)NSString *workDetailedAddress;

@end

NS_ASSUME_NONNULL_END

接下來就是在消息控制器里加入我門自定義的氣泡cell了:

#define kMessageType @"TIM_CUSTOM_MESSAGE_TYPE"
#define kMessageBody @"TIM_CUSTOM_MESSAGE_CONTENT"

// MARK: - bubbleType

#define  kTIM_CUSTOM_MESSAGE_CHAT_RESUME_INFO @"TIM_CUSTOM_MESSAGE_CHAT_RESUME_INFO"
#define kTIM_CUSTOM_MESSAGE_CHAT_POSITIONS_INFO @"TIM_CUSTOM_MESSAGE_CHAT_POSITIONS_INFO"

TMessageController.h:

#import <UIKit/UIKit.h>
#import "TMessageCell.h"
#import "TConversationCell.h"

@class TMessageController;
@protocol TMessageControllerDelegate <NSObject>
- (void)didTapInMessageController:(TMessageController *)controller;
- (void)didHideMenuInMessageController:(TMessageController *)controller;
- (BOOL)messageController:(TMessageController *)controller willShowMenuInView:(UIView *)view;
- (void)messageController:(TMessageController *)controller didSelectMessages:(NSMutableArray *)msgs atIndex:(NSInteger)index;
@end

@interface TMessageController : UIViewController
@property (nonatomic, weak) id<TMessageControllerDelegate> delegate;
- (void)sendMessage:(TMessageCellData *)msg;
- (void)scrollToBottom:(BOOL)animate;
- (void)setConversation:(TConversationCellData *)conversation;
- (void)sendImageMessage:(UIImage *)image;
- (void)sendVideoMessage:(NSURL *)url;
- (void)sendFileMessage:(NSURL *)url;

// MARK: - add
- (void)sendCompanyInfoMessage:(NSString *)companyJsonContent;


- (void)sendContctInfoAndResume:(NSString *)contactInfoContent;

@end

TMessageController.m:(致謝新增或者改動的幾個method):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSObject *data = _uiMsgs[indexPath.row];
    TMessageCell *cell = nil;
    if([data isKindOfClass:[TTextMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TTextMessageCell_ReuseId];
        if(!cell){
            cell = [[TTextMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TTextMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TVoiceMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TVoiceMessageCell_ReuseId];
        if(!cell){
            cell = [[TVoiceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVoiceMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TImageMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TImageMessageCell_ReuseId];
        if(!cell){
            cell = [[TImageMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TImageMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TSystemMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TSystemMessageCell_ReuseId];
        if(!cell){
            cell = [[TSystemMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TSystemMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TFaceMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TFaceMessageCell_ReuseId];
        if(!cell){
            cell = [[TFaceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFaceMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TVideoMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TVideoMessageCell_ReuseId];
        if(!cell){
            cell = [[TVideoMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVideoMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TFileMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TFileMessageCell_ReuseId];
        if(!cell){
            cell = [[TFileMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFileMessageCell_ReuseId];
            cell.delegate = self;
        }
        // MARK: - ####################add
    } else if ([data isKindOfClass:[CompanyInfoCellData class]]) {
        cell = [tableView dequeueReusableCellWithIdentifier:[CompanyInfoCell cellIdentifier]];
        if (!cell) {
            cell = [[CompanyInfoCell alloc] initWithStyle:0 reuseIdentifier:[CompanyInfoCell cellIdentifier]];
            cell.delegate = self;
            ((CompanyInfoCell *)cell).companyInfoDelegate = self;

        }
    } else if ([data isKindOfClass:[InfoCellData class]]) {
        // MARK: - add
        cell = [tableView dequeueReusableCellWithIdentifier:[InfoCell cellIdentifier]];
        if (!cell) {
            cell = [[InfoCell alloc] initWithStyle:0 reuseIdentifier:[InfoCell cellIdentifier]];
            cell.delegate = self;
            ((InfoCell *)cell).infoDelegate = self;
        }
    }
    [cell setData:_uiMsgs[indexPath.row]];
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat height = 0;
    if(_heightCache.count > indexPath.row){
        return [_heightCache[indexPath.row] floatValue];
    }
    NSObject *data = _uiMsgs[indexPath.row];
    if([data isKindOfClass:[TTextMessageCellData class]]){
        TTextMessageCellData *text = _uiMsgs[indexPath.row];
        TTextMessageCell *cell = [[TTextMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TTextMessageCell_ReuseId];
        height = [cell getHeight:text];
    }else if([data isKindOfClass:[TVoiceMessageCellData class]]){
        TVoiceMessageCellData *voice = _uiMsgs[indexPath.row];
        TVoiceMessageCell *cell = [[TVoiceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVoiceMessageCell_ReuseId];
        height = [cell getHeight:voice];
    }
    else if([data isKindOfClass:[TImageMessageCellData class]]){
        TImageMessageCellData *image = _uiMsgs[indexPath.row];
        TImageMessageCell *cell = [[TImageMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TImageMessageCell_ReuseId];
        height = [cell getHeight:image];
    }
    else if([data isKindOfClass:[TSystemMessageCellData class]]){
        TSystemMessageCellData *system = _uiMsgs[indexPath.row];
        TSystemMessageCell *cell = [[TSystemMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TSystemMessageCell_ReuseId];
        height = [cell getHeight:system];
    }
    else if([data isKindOfClass:[TFaceMessageCellData class]]){
        TFaceMessageCellData *face = _uiMsgs[indexPath.row];
        TFaceMessageCell *cell = [[TFaceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFaceMessageCell_ReuseId];
        height = [cell getHeight:face];
    }
    else if([data isKindOfClass:[TVideoMessageCellData class]]){
        TVideoMessageCellData *video = _uiMsgs[indexPath.row];
        TVideoMessageCell *cell = [[TVideoMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVideoMessageCell_ReuseId];
        height = [cell getHeight:video];
    }
    else if([data isKindOfClass:[TFileMessageCellData class]]){
        TFileMessageCellData *file = _uiMsgs[indexPath.row];
        TFileMessageCell *cell = [[TFileMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFileMessageCell_ReuseId];
        height = [cell getHeight:file];
        // MARK:######################### - 計算高度
    } else if ([data isKindOfClass:[CompanyInfoCellData class]]) {
        CompanyInfoCellData *info = _uiMsgs[indexPath.row];
        CompanyInfoCell *cell = [[CompanyInfoCell alloc] initWithStyle:0 reuseIdentifier:NSStringFromClass([CompanyInfoCell class])];
        height = [cell getHeight:info];
    } else if ([data isKindOfClass:[InfoCellData class]]) {
        // MARK: - add
        InfoCellData *info = _uiMsgs[indexPath.row];
        InfoCell *cell = [[InfoCell alloc] initWithStyle:0 reuseIdentifier:NSStringFromClass([InfoCell class])];
        height = [cell getHeight:info];
    }
    [_heightCache insertObject:[NSNumber numberWithFloat:height] atIndex:indexPath.row];
    return height;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSObject *data = _uiMsgs[indexPath.row];
    TMessageCell *cell = nil;
    if([data isKindOfClass:[TTextMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TTextMessageCell_ReuseId];
        if(!cell){
            cell = [[TTextMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TTextMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TVoiceMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TVoiceMessageCell_ReuseId];
        if(!cell){
            cell = [[TVoiceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVoiceMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TImageMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TImageMessageCell_ReuseId];
        if(!cell){
            cell = [[TImageMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TImageMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TSystemMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TSystemMessageCell_ReuseId];
        if(!cell){
            cell = [[TSystemMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TSystemMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TFaceMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TFaceMessageCell_ReuseId];
        if(!cell){
            cell = [[TFaceMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFaceMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TVideoMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TVideoMessageCell_ReuseId];
        if(!cell){
            cell = [[TVideoMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TVideoMessageCell_ReuseId];
            cell.delegate = self;
        }
    }
    else if([data isKindOfClass:[TFileMessageCellData class]]){
        cell = [tableView dequeueReusableCellWithIdentifier:TFileMessageCell_ReuseId];
        if(!cell){
            cell = [[TFileMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TFileMessageCell_ReuseId];
            cell.delegate = self;
        }
        // MARK: - ####################add
    } else if ([data isKindOfClass:[CompanyInfoCellData class]]) {
        cell = [tableView dequeueReusableCellWithIdentifier:[CompanyInfoCell cellIdentifier]];
        if (!cell) {
            cell = [[CompanyInfoCell alloc] initWithStyle:0 reuseIdentifier:[CompanyInfoCell cellIdentifier]];
            cell.delegate = self;
            ((CompanyInfoCell *)cell).companyInfoDelegate = self;

        }
    } else if ([data isKindOfClass:[InfoCellData class]]) {
        // MARK: - add
        cell = [tableView dequeueReusableCellWithIdentifier:[InfoCell cellIdentifier]];
        if (!cell) {
            cell = [[InfoCell alloc] initWithStyle:0 reuseIdentifier:[InfoCell cellIdentifier]];
            cell.delegate = self;
            ((InfoCell *)cell).infoDelegate = self;
        }
    }
    [cell setData:_uiMsgs[indexPath.row]];
    return cell;
}
#warning #############################add
// MARK: - #########################Add
-(void)sendCompanyInfoMessage:(NSString *)companyJsonContent {
    CompanyInfoCellData *data = [CompanyInfoCellData new];
    data.totalContent = [self buildExWithMessageType:InfoMessagePostion messageBody:companyJsonContent];
    data.head = TUIKitResource(@"default_head");
    data.isSelf = YES;
    [self sendMessage:data];
}

// MARK: - 發(fā)送聯(lián)系方式  電話 微信 簡歷
- (void)sendContctInfoAndResume:(NSString *)contactInfoContent  {
    InfoCellData *data = [InfoCellData new];
    data.totalContent = [self buildExWithMessageType:0 messageBody:contactInfoContent];
    data.head = TUIKitResource(@"default_head");
    data.isSelf = YES;
    [self sendMessage:data];
    
}


- (TIMMessage *)transIMMsgFromUIMsg:(TMessageCellData *)data
{
    TIMMessage *msg = [[TIMMessage alloc] init];
    if([data isKindOfClass:[TTextMessageCellData class]]){
        TIMTextElem *imText = [[TIMTextElem alloc] init];
        TTextMessageCellData *text = (TTextMessageCellData *)data;
        imText.text = text.content;
        [msg addElem:imText];
    }
    else if([data isKindOfClass:[TFaceMessageCellData class]]){
        TIMFaceElem *imImage = [[TIMFaceElem alloc] init];
        TFaceMessageCellData *image = (TFaceMessageCellData *)data;
        imImage.index = (int)image.groupIndex;
        imImage.data = [image.faceName dataUsingEncoding:NSUTF8StringEncoding];
        [msg addElem:imImage];
    }
    else if([data isKindOfClass:[TImageMessageCellData class]]){
        TIMImageElem *imImage = [[TIMImageElem alloc] init];
        TImageMessageCellData *uiImage = (TImageMessageCellData *)data;
        imImage.path = uiImage.path;
        [msg addElem:imImage];
    }
    else if([data isKindOfClass:[TVideoMessageCellData class]]){
        TIMVideoElem *imVideo = [[TIMVideoElem alloc] init];
        TVideoMessageCellData *uiVideo = (TVideoMessageCellData *)data;
        imVideo.videoPath = uiVideo.videoPath;
        imVideo.snapshotPath = uiVideo.snapshotPath;
        imVideo.snapshot = [[TIMSnapshot alloc] init];
        imVideo.snapshot.width = uiVideo.snapshotItem.size.width;
        imVideo.snapshot.height = uiVideo.snapshotItem.size.height;
        imVideo.video = [[TIMVideo alloc] init];
        imVideo.video.duration = (int)uiVideo.videoItem.duration;
        imVideo.video.type = uiVideo.videoItem.type;
        [msg addElem:imVideo];
    }
    else if([data isKindOfClass:[TVoiceMessageCellData class]]){
        TIMSoundElem *imSound = [[TIMSoundElem alloc] init];
        TVoiceMessageCellData *uiSound = (TVoiceMessageCellData *)data;
        imSound.path = uiSound.path;
        imSound.second = uiSound.duration;
        imSound.dataSize = uiSound.length;
        [msg addElem:imSound];
    }
    else if([data isKindOfClass:[TFileMessageCellData class]]){
        TIMFileElem *imFile = [[TIMFileElem alloc] init];
        TFileMessageCellData *uiFile = (TFileMessageCellData *)data;
        imFile.path = uiFile.path;
        imFile.fileSize = uiFile.length;
        imFile.filename = uiFile.fileName;
        [msg addElem:imFile];
    } else if ([data isKindOfClass:[CompanyInfoCellData class]]) {
        // MARK: #######################公司信息
        //        TCompanyInfoElement *ele = [TCompanyInfoElement new];
        TIMCustomElem *elt = [TIMCustomElem new];
        CompanyInfoCellData *infoData = (CompanyInfoCellData *)data;
        elt.data = [infoData.totalContent mj_JSONData];
        elt.ext = infoData.totalContent;
        [msg  addElem:elt];
        // MARK: - j#############交換聯(lián)系方式
    } else if ([data isKindOfClass:[InfoCellData class]]) {
        TIMCustomElem *elt = [TIMCustomElem new];
        InfoCellData *infoData = (InfoCellData *)data;
        elt.data = [infoData.totalContent mj_JSONData];
        elt.ext = infoData.totalContent;
        [msg  addElem:elt];
    }
    data.custom = msg;
    return msg;
    
}


// MARK: - 加載消息去區(qū)分
- (NSMutableArray *)transUIMsgFromIMMsg:(NSArray *)msgs
{
    NSMutableArray *uiMsgs = [NSMutableArray array];
    for (NSInteger k = msgs.count - 1; k >= 0; --k) {
        TIMMessage *msg = msgs[k];
        if(![[[msg getConversation] getReceiver] isEqualToString:_conv.convId]){
            continue;
        }
        if(msg.status == TIM_MSG_STATUS_HAS_DELETED){
            continue;
        }
        TMessageCellData *dateMsg = [self transSystemMsgFromDate:msg.timestamp];
        if(dateMsg){
            _msgForDate = msg;
            dateMsg.custom = nil;
            [uiMsgs addObject:dateMsg];
        }
        if(msg.status == TIM_MSG_STATUS_LOCAL_REVOKED){
            TSystemMessageCellData *revoke = [[TSystemMessageCellData alloc] init];
            revoke.content = @"你撤回了一條消息";
            revoke.custom = msg;
            [uiMsgs addObject:revoke];
            continue;
        }
        for (int i = 0; i < msg.elemCount; ++i) {
            TIMElem *elem = [msg getElem:i];
            TMessageCellData *data = nil;
            if([elem isKindOfClass:[TIMTextElem class]]){
                TIMTextElem *text = (TIMTextElem *)elem;
                TTextMessageCellData *textData = [[TTextMessageCellData alloc] init];
                textData.content = text.text;
                data = textData;
            } else if ([elem isKindOfClass:[TIMCustomElem class]]) {
                // MARK: #############################################add
                TIMCustomElem *elt = (TIMCustomElem*) elem;
 MARK: - 這里是根據(jù)擴展字段里的type和content來進行區(qū)分,這里還有一個坑底那就是 ext擴展字段里的json傳據(jù)后臺說只能進行base64編碼传泊,然后客戶端這里再進行解碼,
                NSString *extension =  [[self base64DecodeString:elt.ext] stringByReplacingOccurrencesOfString:@"this is a example" withString:@""];
//                NSString *extension =  [self base64DecodeString:elt.ext];
//                NSInteger type = [[((NSDictionary *)[extension mj_JSONObject]) objectForKey:kMessageType] integerValue];
                 NSString * type = [((NSDictionary *)[extension mj_JSONObject]) objectForKey:kMessageType];
                // MARK: - 區(qū)分消息類型
                /*if (type == InfoMessageTypeTel ||  type == InfoMessageTypeWeChat  ||  type == InfoMessageResume) {
                    // MARK: - 微信 電話 簡歷
                    InfoCellData *infoData = [InfoCellData new];
                    infoData.totalContent = extension;
                    data = infoData;
                } else if (type == InfoMessagePostion ) {
                    // MARK: - 職位信息
                    CompanyInfoCellData *companData  = [CompanyInfoCellData new];
                    companData.totalContent = extension;
                    data = companData;
                }*/
                
                if ([type isEqualToString:kTIM_CUSTOM_MESSAGE_CHAT_POSITIONS_INFO] ) {
                    // MARK: - 職位信息
                    CompanyInfoCellData *companData  = [CompanyInfoCellData new];
                    companData.totalContent = extension;
                    data = companData;
                }
            }
            else if([elem isKindOfClass:[TIMFaceElem class]]){
                TIMFaceElem *face = (TIMFaceElem *)elem;
                TFaceMessageCellData *faceData = [[TFaceMessageCellData alloc] init];
                faceData.groupIndex = face.index;
                faceData.faceName = [[NSString alloc] initWithData:face.data encoding:NSUTF8StringEncoding];
                for (TFaceGroup *group in [[TUIKit sharedInstance] getConfig].faceGroups) {
                    if(group.groupIndex == faceData.groupIndex){
                        NSString *path = [group.groupPath stringByAppendingPathComponent:faceData.faceName];
                        faceData.path = path;
                        break;
                    }
                }
                data = faceData;
            } else if([elem isKindOfClass:[TIMImageElem class]]){
                TIMImageElem *image = (TIMImageElem *)elem;
                TImageMessageCellData *imageData = [[TImageMessageCellData alloc] init];
                imageData.path = image.path;
                imageData.items = [NSMutableArray array];
                for (TIMImage *item in image.imageList) {
                    TImageItem *itemData = [[TImageItem alloc] init];
                    itemData.uuid = item.uuid;
                    itemData.size = CGSizeMake(item.width, item.height);
                    itemData.url = item.url;
                    if(item.type == TIM_IMAGE_TYPE_THUMB){
                        itemData.type = TImage_Type_Thumb;
                    }
                    else if(item.type == TIM_IMAGE_TYPE_LARGE){
                        itemData.type = TImage_Type_Large;
                    }
                    else if(item.type == TIM_IMAGE_TYPE_ORIGIN){
                        itemData.type = TImage_Type_Origin;
                    }
                    [imageData.items addObject:itemData];
                }
                data = imageData;
            }else if([elem isKindOfClass:[TIMSoundElem class]]){
                TIMSoundElem *sound = (TIMSoundElem *)elem;
                TVoiceMessageCellData *soundData = [[TVoiceMessageCellData alloc] init];
                soundData.duration = sound.second;
                soundData.length = sound.dataSize;
                soundData.uuid = sound.uuid;
                
                data = soundData;
            }else if([elem isKindOfClass:[TIMVideoElem class]]){
                TIMVideoElem *video = (TIMVideoElem *)elem;
                TVideoMessageCellData *videoData = [[TVideoMessageCellData alloc] init];
                videoData.videoPath = video.videoPath;
                videoData.snapshotPath = video.snapshotPath;
                
                videoData.videoItem = [[TVideoItem alloc] init];
                videoData.videoItem.uuid = video.video.uuid;
                videoData.videoItem.type = video.video.type;
                videoData.videoItem.length = video.video.size;
                videoData.videoItem.duration = video.video.duration;
                
                videoData.snapshotItem = [[TSnapshotItem alloc] init];
                videoData.snapshotItem.uuid = video.snapshot.uuid;
                videoData.snapshotItem.type = video.snapshot.type;
                videoData.snapshotItem.length = video.snapshot.size;
                videoData.snapshotItem.size = CGSizeMake(video.snapshot.width, video.snapshot.height);
                
                data = videoData;
            }
            else if([elem isKindOfClass:[TIMFileElem class]]){
                TIMFileElem *file = (TIMFileElem *)elem;
                TFileMessageCellData *fileData = [[TFileMessageCellData alloc] init];
                fileData.path = file.path;
                fileData.fileName = file.filename;
                fileData.length = file.fileSize;
                fileData.uuid = file.uuid;
                
                data = fileData;
            }
            else if([elem isKindOfClass:[TIMCustomElem class]]){
                TIMCustomElem *custom = (TIMCustomElem *)elem;
                TSystemMessageCellData *systemData = [[TSystemMessageCellData alloc] init];
                systemData.content = custom.ext;
                
                data = systemData;
            }
            if([[msg getConversation] getType] == TIM_GROUP && !msg.isSelf){
                data.showName = YES;
            }
            if(data){
                data.isSelf = msg.isSelf;
                data.head = TUIKitResource(@"default_head");
                //data.name = msg.sender;
                if([[msg getConversation] getType] == TIM_GROUP){
                    data.name = [msg getSenderGroupMemberProfile].nameCard;
                }
                else if([[msg getConversation] getType] == TIM_C2C){
                    data.name = [msg getSenderProfile].nickname;
                }
                if(data.name.length == 0){
                    data.name = msg.sender;
                }
                if(msg.status == TIM_MSG_STATUS_SEND_SUCC){
                    data.status = Msg_Status_Succ;
                    [uiMsgs addObject:data];
                }
                else if(msg.status == TIM_MSG_STATUS_SEND_FAIL){
                    data.status = Msg_Status_Fail;
                    [uiMsgs addObject:data];
                }
                data.custom = msg;
            }
            
            if([elem isKindOfClass:[TIMGroupTipsElem class]]){
                TIMGroupTipsElem *tips = (TIMGroupTipsElem *)elem;
                switch (tips.type) {
                    case TIM_GROUP_TIPS_TYPE_INFO_CHANGE:
                    {
                        for (TIMGroupTipsElemGroupInfo *info in tips.groupChangeList) {
                            TSystemMessageCellData *data = [[TSystemMessageCellData alloc] init];
                            switch (info.type) {
                                case TIM_GROUP_INFO_CHANGE_GROUP_NAME:
                                {
                                    data.content = [NSString stringWithFormat:@"\"%@\"修改群名為\"%@\"", tips.opUser, info.value];
                                }
                                    break;
                                case TIM_GROUP_INFO_CHANGE_GROUP_INTRODUCTION:
                                {
                                    data.content = [NSString stringWithFormat:@"\"%@\"修改群簡介為\"%@\"", tips.opUser, info.value];
                                }
                                    break;
                                case TIM_GROUP_INFO_CHANGE_GROUP_NOTIFICATION:
                                {
                                    data.content = [NSString stringWithFormat:@"\"%@\"修改群公告為\"%@\"", tips.opUser, info.value];
                                }
                                    break;
                                case TIM_GROUP_INFO_CHANGE_GROUP_OWNER:
                                {
                                    data.content = [NSString stringWithFormat:@"\"%@\"修改群主為\"%@\"", tips.opUser, info.value];
                                }
                                    break;
                                default:
                                    break;
                            }
                            [uiMsgs addObject:data];
                        }
                    }
                        break;
                    case TIM_GROUP_TIPS_TYPE_KICKED:
                    {
                        TSystemMessageCellData *data = [[TSystemMessageCellData alloc] init];
                        NSString *users = [tips.userList componentsJoinedByString:@"鸭巴、"];
                        data.content = [NSString stringWithFormat:@"\"%@\"將\"%@\"剔出群組", tips.opUser, users];
                        [uiMsgs addObject:data];
                    }
                        break;
                    case TIM_GROUP_TIPS_TYPE_INVITE:
                    {
                        TSystemMessageCellData *data = [[TSystemMessageCellData alloc] init];
                        NSString *users = [tips.userList componentsJoinedByString:@"眷细、"];
                        data.content = [NSString stringWithFormat:@"\"%@\"邀請\"%@\"加入群組", tips.opUser, users];
                        [uiMsgs addObject:data];
                    }
                        break;
                    default:
                        break;
                }
            }
        }
    }
    return uiMsgs;
}

- (NSString *)buildExWithMessageType:(NSInteger)type messageBody:(NSString *)messageBody {
    /*
     @{
     @"messgeType": @"1"  // 0電話 1微信 2簡歷 3職位 4
     @"messageBody":@" {
     @"messageContent:@"xxxxx",
     @"messageIcon":@"http://xxx.png",
     ...
     }"
     }*/
    NSMutableDictionary  *extDic = [NSMutableDictionary new];
    [extDic setObject:[NSString stringWithFormat:@"%zd",type] forKey:kMessageType];
    [extDic setObject:messageBody forKey:kMessageBody];
    return [extDic mj_JSONString];
}

// MARK: - 解碼
-(NSString *)base64DecodeString:(NSString *)string{
    NSData *data=[[NSData alloc]initWithBase64EncodedString:string options:0];
    return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}

聊天會話列表可以自己自定義:
ChatListVC .m:

// MARK: - viewController's life Circle
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // MARK: - 監(jiān)聽消息
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateConversations) name:TUIKitNotification_TIMRefreshListener object:nil];
    [self updateConversations];
}

// MARK: - update message notify
- (void)updateConversations {
    _dataArray = [NSMutableArray arrayWithArray:[[TIMManager sharedInstance]getConversationList]];
    int sum = 0;
    for (TIMConversation *con in _dataArray) {
        sum = sum + [con getUnReadMessageNum];
    }
    //未讀消息數(shù)
    if (sum >0) {
        self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%i",sum];
    } else {
        self.tabBarItem.badgeValue = nil;
    }
    [_tableView reloadData];
}

// MARK: - UITableViewDataSource &Delegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _dataArray.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ChatListCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([ChatListCell class])];
    if (!cell) {
        cell = [[ChatListCell alloc] initWithStyle:0 reuseIdentifier:NSStringFromClass([ChatListCell class])];
    }
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    [cell setCellWithConversation:_dataArray[indexPath.row]];
    return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 72;
}

/*
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 5.0;
}

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 5.0;
}
 */


-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    ChatViewController *chat = [ChatViewController new];
    chat.conversation = [self _convertConversationToConversationData:_dataArray[indexPath.row]];
    chat.hidesBottomBarWhenPushed = YES;
    [self.navigationController pushViewController:chat animated:YES];
}

// MARK: - delete Action
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewCellEditingStyleDelete;
}

- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return @"刪除";
}

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // MARK: - 刪除會話
    TIMConversation *con = _dataArray[indexPath.row];
    [[TIMManager sharedInstance] deleteConversationAndMessages:TIM_C2C receiver:con.getReceiver];
    
    [_dataArray removeObjectAtIndex:indexPath.row];
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
}

#warning ###################################消息轉(zhuǎn)換方法
- (TConversationCellData *)_convertConversationToConversationData:(TIMConversation *)conv {
    //[conv getMessage:[[TUIKit sharedInstance] getConfig].msgCountPerRequest last:nil succ:nil fail:nil];
    TIMMessage *msg = [conv getLastMsg];
    TConversationCellData *data = [[TConversationCellData alloc] init];
    data.unRead = [conv getUnReadMessageNum];
    data.time = [self getDateDisplayString:msg.timestamp];
    data.subTitle = [self getLastDisplayString:conv];
    if([conv getType] == TIM_C2C){
        // MARK: - 對方的頭像和名字
        data.head = TUIKitResource(@"default_head");
    }else if([conv getType] == TIM_GROUP){
        data.head = TUIKitResource(@"default_group");
    }
    data.convId = [conv getReceiver];
    data.convType = (TConvType)[conv getType];
    
    if(data.convType == TConv_Type_C2C){
        data.title = data.convId;
    }
    else if(data.convType == TConv_Type_Group){
        data.title = [conv getGroupName];
    }
    return data;
}

- (NSString *)getLastDisplayString:(TIMConversation *)conv {
    NSString *str = @"";
    TIMMessageDraft *draft = [conv getDraft];
    // MARK: - 草稿內(nèi)容
    if(draft){
        for (int i = 0; i < draft.elemCount; ++i) {
            TIMElem *elem = [draft getElem:i];
            if([elem isKindOfClass:[TIMTextElem class]]){
                TIMTextElem *text = (TIMTextElem *)elem;
                str = [NSString stringWithFormat:@"[草稿]%@", text.text];
                break;
            }
            else{
                continue;
            }
        }
        return str;
    }
    
    TIMMessage *msg = [conv getLastMsg];
    if(msg.status == TIM_MSG_STATUS_LOCAL_REVOKED){
        if(msg.isSelf){
            return @"你撤回了一條消息";
        }
        else{
            return [NSString stringWithFormat:@"\"%@\"撤回了一條消息", msg.sender];
        }
    }
    for (int i = 0; i < msg.elemCount; ++i) {
        TIMElem *elem = [msg getElem:i];
        if([elem isKindOfClass:[TIMTextElem class]]){
            TIMTextElem *text = (TIMTextElem *)elem;
            str = text.text;
            break;
        }
        else if([elem isKindOfClass:[TIMCustomElem class]]){
            TIMCustomElem *custom = (TIMCustomElem *)elem;
            str = custom.ext;
            break;
        }
        else if([elem isKindOfClass:[TIMImageElem class]]){
            str = @"[圖片]";
            break;
        }
        else if([elem isKindOfClass:[TIMSoundElem class]]){
            str = @"[語音]";
            break;
        }
        else if([elem isKindOfClass:[TIMVideoElem class]]){
            str = @"[視頻]";
            break;
        }
        else if([elem isKindOfClass:[TIMFaceElem class]]){
            str = @"[動畫表情]";
            break;
        }
        else if([elem isKindOfClass:[TIMFileElem class]]){
            str = @"[文件]";
            break;
        }
        else if([elem isKindOfClass:[TIMGroupTipsElem class]]){
            TIMGroupTipsElem *tips = (TIMGroupTipsElem *)elem;
            switch (tips.type) {
                case TIM_GROUP_TIPS_TYPE_INFO_CHANGE:
                {
                    for (TIMGroupTipsElemGroupInfo *info in tips.groupChangeList) {
                        switch (info.type) {
                            case TIM_GROUP_INFO_CHANGE_GROUP_NAME:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群名為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_INTRODUCTION:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群簡介為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_NOTIFICATION:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群公告為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_OWNER:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群主為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            default:
                                break;
                        }
                    }
                }
                    break;
                case TIM_GROUP_TIPS_TYPE_KICKED:
                {
                    NSString *users = [tips.userList componentsJoinedByString:@"、"];
                    str = [NSString stringWithFormat:@"\"%@\"將\"%@\"剔出群組", tips.opUser, users];
                }
                    break;
                case TIM_GROUP_TIPS_TYPE_INVITE:
                {
                    NSString *users = [tips.userList componentsJoinedByString:@"鹃祖、"];
                    str = [NSString stringWithFormat:@"\"%@\"邀請\"%@\"加入群組", tips.opUser, users];
                }
                    break;
                default:
                    break;
            }
        }
        else{
            continue;
        }
    }
    return str;
}

// MARK: -最后一條消息的發(fā)送時間
- (NSString *)getDateDisplayString:(NSDate *)date
{
    NSCalendar *calendar = [ NSCalendar currentCalendar ];
    int unit = NSCalendarUnitDay | NSCalendarUnitMonth |  NSCalendarUnitYear ;
    NSDateComponents *nowCmps = [calendar components:unit fromDate:[ NSDate date ]];
    NSDateComponents *myCmps = [calendar components:unit fromDate:date];
    NSDateFormatter *dateFmt = [[NSDateFormatter alloc ] init ];
    
    NSDateComponents *comp =  [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday fromDate:date];
    
    if (nowCmps.year != myCmps.year) {
        dateFmt.dateFormat = @"yyyy/MM/dd";
    }
    else{
        if (nowCmps.day==myCmps.day) {
            dateFmt.AMSymbol = @"上午";
            dateFmt.PMSymbol = @"下午";
            dateFmt.dateFormat = @"aaa hh:mm";
        } else if((nowCmps.day-myCmps.day)==1) {
            dateFmt.AMSymbol = @"上午";
            dateFmt.PMSymbol = @"下午";
            dateFmt.dateFormat = @"昨天";
        } else {
            if ((nowCmps.day-myCmps.day) <=7) {
                switch (comp.weekday) {
                    case 1:
                        dateFmt.dateFormat = @"星期日";
                        break;
                    case 2:
                        dateFmt.dateFormat = @"星期一";
                        break;
                    case 3:
                        dateFmt.dateFormat = @"星期二";
                        break;
                    case 4:
                        dateFmt.dateFormat = @"星期三";
                        break;
                    case 5:
                        dateFmt.dateFormat = @"星期四";
                        break;
                    case 6:
                        dateFmt.dateFormat = @"星期五";
                        break;
                    case 7:
                        dateFmt.dateFormat = @"星期六";
                        break;
                    default:
                        break;
                }
            }else {
                dateFmt.dateFormat = @"yyyy/MM/dd";
            }
        }
    }
    return [dateFmt stringFromDate:date];
}

ChatListCell.m:

- (void)setCellWithConversation:(TIMConversation *)model {
    if (model) {
        _model = model;
        [_avatar sd_setImageWithURL:[NSURL URLWithString:@"https://avatars0.githubusercontent.com/u/16589546?s=460&v=4"] placeholderImage:[UIImage imageNamed:@"AppIcon"]];
        _name.text = [model getReceiver];
        _time.text = [self getDateDisplayString:[model getLastMsg].timestamp];
        if (![model getUnReadMessageNum]) {
            _badge.hidden = YES;
        } else  {
            _badge.hidden = NO;
            _badge.text = [NSString stringWithFormat:@"%i",[model getUnReadMessageNum]];
        }
        _recieve.layer.borderColor = [UIColor orangeColor].CGColor;
        _recieve.layer.borderWidth = 1.0;
        _recieve.textColor = [UIColor orangeColor];
        BOOL isMe = [[model getLastMsg].sender isEqualToString:@"user1"];
        _recieve.text = isMe ? @"送達":@"已讀";
        _content.text = [self getLastDisplayString:model];
    }
}


- (NSString *)getLastDisplayString:(TIMConversation *)conv
{
    NSString *str = @"";
    TIMMessageDraft *draft = [conv getDraft];
    if(draft){
        for (int i = 0; i < draft.elemCount; ++i) {
            TIMElem *elem = [draft getElem:i];
            if([elem isKindOfClass:[TIMTextElem class]]){
                TIMTextElem *text = (TIMTextElem *)elem;
                str = [NSString stringWithFormat:@"[草稿]%@", text.text];
                break;
            }
            else{
                continue;
            }
        }
        return str;
    }
    
    TIMMessage *msg = [conv getLastMsg];
    if(msg.status == TIM_MSG_STATUS_LOCAL_REVOKED){
        if(msg.isSelf){
            return @"你撤回了一條消息";
        }
        else{
            return [NSString stringWithFormat:@"\"%@\"撤回了一條消息", msg.sender];
        }
    }
    for (int i = 0; i < msg.elemCount; ++i) {
        TIMElem *elem = [msg getElem:i];
        if([elem isKindOfClass:[TIMTextElem class]]){
            TIMTextElem *text = (TIMTextElem *)elem;
            str = text.text;
            break;
        }
        else if([elem isKindOfClass:[TIMCustomElem class]]){
            TIMCustomElem *custom = (TIMCustomElem *)elem;
MARK://解碼
            str = [self base64DecodeString: custom.ext];
            break;
        }
        else if([elem isKindOfClass:[TIMImageElem class]]){
            str = @"[圖片]";
            break;
        }
        else if([elem isKindOfClass:[TIMSoundElem class]]){
            str = @"[語音]";
            break;
        }
        else if([elem isKindOfClass:[TIMVideoElem class]]){
            str = @"[視頻]";
            break;
        }
        else if([elem isKindOfClass:[TIMFaceElem class]]){
            str = @"[動畫表情]";
            break;
        }
        else if([elem isKindOfClass:[TIMFileElem class]]){
            str = @"[文件]";
            break;
        }
        else if([elem isKindOfClass:[TIMGroupTipsElem class]]){
            TIMGroupTipsElem *tips = (TIMGroupTipsElem *)elem;
            switch (tips.type) {
                case TIM_GROUP_TIPS_TYPE_INFO_CHANGE:
                {
                    for (TIMGroupTipsElemGroupInfo *info in tips.groupChangeList) {
                        switch (info.type) {
                            case TIM_GROUP_INFO_CHANGE_GROUP_NAME:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群名為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_INTRODUCTION:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群簡介為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_NOTIFICATION:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群公告為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            case TIM_GROUP_INFO_CHANGE_GROUP_OWNER:
                            {
                                str = [NSString stringWithFormat:@"\"%@\"修改群主為\"%@\"", tips.opUser, info.value];
                            }
                                break;
                            default:
                                break;
                        }
                    }
                }
                    break;
                case TIM_GROUP_TIPS_TYPE_KICKED:
                {
                    NSString *users = [tips.userList componentsJoinedByString:@"溪椎、"];
                    str = [NSString stringWithFormat:@"\"%@\"將\"%@\"剔出群組", tips.opUser, users];
                }
                    break;
                case TIM_GROUP_TIPS_TYPE_INVITE:
                {
                    NSString *users = [tips.userList componentsJoinedByString:@"、"];
                    str = [NSString stringWithFormat:@"\"%@\"邀請\"%@\"加入群組", tips.opUser, users];
                }
                    break;
                default:
                    break;
            }
        }
        else{
            continue;
        }
    }
    return str;
}

-(NSString *)base64DecodeString:(NSString *)string{
    NSData *data=[[NSData alloc]initWithBase64EncodedString:string options:0];
    return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}

- (NSString *)getDateDisplayString:(NSDate *)date {
    NSCalendar *calendar = [ NSCalendar currentCalendar ];
    int unit = NSCalendarUnitDay | NSCalendarUnitMonth |  NSCalendarUnitYear ;
    NSDateComponents *nowCmps = [calendar components:unit fromDate:[ NSDate date ]];
    NSDateComponents *myCmps = [calendar components:unit fromDate:date];
    NSDateFormatter *dateFmt = [[NSDateFormatter alloc ] init ];
    
    NSDateComponents *comp =  [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday fromDate:date];
    
    if (nowCmps.year != myCmps.year) {
        dateFmt.dateFormat = @"yyyy/MM/dd";
    }
    else{
        if (nowCmps.day==myCmps.day) {
            dateFmt.AMSymbol = @"上午";
            dateFmt.PMSymbol = @"下午";
            dateFmt.dateFormat = @"aaa hh:mm";
        } else if((nowCmps.day-myCmps.day)==1) {
            dateFmt.AMSymbol = @"上午";
            dateFmt.PMSymbol = @"下午";
            dateFmt.dateFormat = @"昨天";
        } else {
            if ((nowCmps.day-myCmps.day) <=7) {
                switch (comp.weekday) {
                    case 1:
                        dateFmt.dateFormat = @"星期日";
                        break;
                    case 2:
                        dateFmt.dateFormat = @"星期一";
                        break;
                    case 3:
                        dateFmt.dateFormat = @"星期二";
                        break;
                    case 4:
                        dateFmt.dateFormat = @"星期三";
                        break;
                    case 5:
                        dateFmt.dateFormat = @"星期四";
                        break;
                    case 6:
                        dateFmt.dateFormat = @"星期五";
                        break;
                    case 7:
                        dateFmt.dateFormat = @"星期六";
                        break;
                    default:
                        break;
                }
            }else {
                dateFmt.dateFormat = @"yyyy/MM/dd";
            }
        }
    }
    return [dateFmt stringFromDate:date];
}

氣泡自定義擴展字段消息格式如下:

{"TIM_CUSTOM_MESSAGE_CONTENT":{"degreeRequirement":"博士","enterpriseName":"深圳市xxx智能科技有限公司","expectJobCity":"101280600","experienceRequirement":"10年以上","financingStage":"天使輪","headPortrait":"http://xxx.oss-cn-hangzhou.aliyuncs.com/S8PeJn_%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190320174739.jpg","launchCommunicativeTimeStamp":1553331133,"nickname":"蘇海峰","positionName":"前端開發(fā)","salaryHighestRequirement":2000.00,"salaryMinimumRequirement":1000.00,"synopsis":"由你發(fā)起的溝通","workDetailedAddress":"深圳市路通網(wǎng)絡(luò)技術(shù)有限公司"},"TIM_CUSTOM_MESSAGE_TYPE":"TIM_CUSTOM_MESSAGE_CHAT_POSITIONS_INFO"}

核心改動的文件就是上面這幾個文件了恬口,讀懂就可以做一些自定義氣泡的一些東東了校读, 具體效果如下:


WechatIMG55.png

WechatIMG57.png

WechatIMG58.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祖能,隨后出現(xiàn)的幾起案子歉秫,更是在濱河造成了極大的恐慌,老刑警劉巖养铸,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雁芙,死亡現(xiàn)場離奇詭異轧膘,居然都是意外死亡,警方通過查閱死者的電腦和手機兔甘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門谎碍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洞焙,你說我怎么就攤上這事蟆淀。” “怎么了澡匪?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵熔任,是天一觀的道長。 經(jīng)常有香客問我唁情,道長笋敞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任荠瘪,我火速辦了婚禮夯巷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哀墓。我一直安慰自己趁餐,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布篮绰。 她就那樣靜靜地躺著后雷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吠各。 梳的紋絲不亂的頭發(fā)上臀突,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音贾漏,去河邊找鬼候学。 笑死,一個胖子當著我的面吹牛纵散,可吹牛的內(nèi)容都是我干的梳码。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼伍掀,長吁一口氣:“原來是場噩夢啊……” “哼掰茶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜜笤,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤濒蒋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后把兔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪伙,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡甸各,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了焰坪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡聘惦,死狀恐怖某饰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情善绎,我是刑警寧澤黔漂,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站禀酱,受9級特大地震影響炬守,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剂跟,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一减途、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧曹洽,春花似錦鳍置、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祭示。三九已至,卻和暖如春辟拷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阐斜。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工衫冻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谒出。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓羽杰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親到推。 傳聞我的和親對象是個殘疾皇子考赛,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件莉测、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評論 4 62
  • 騰訊云IM的sdk中主要提供了 以下幾個消息類 TIMTextElem (文本消息) TIMImageElem (...
    進階的蚊子閱讀 6,535評論 2 0
  • 你颜骤,永遠都是別人眼里的風(fēng)景 一生輾轉(zhuǎn)千萬里,莫問成敗重幾許捣卤,得之坦然忍抽,失之淡然八孝,與其在別人的輝煌里仰望,不如親手點...
    毅自由閱讀 227評論 0 2
  • 這兩天在PMCAFF上看到了一個問題: 下面,我將針對這個問題給出自己的一些解答祟绊。 為什么微信要弱化聯(lián)系人的分組功...
    澄禎閱讀 12,406評論 4 20
  • 親愛的瑜舍家人們楼入, 又是新一周早安! 瑜舍在未來有一個很重要的正在探索孵化中的業(yè)務(wù)板塊是情緒管理牧抽。 健康管理里面屬...
    瑾爺Jaya閱讀 545評論 4 3