由于最近接觸到的項目需要用到聊天功能,關于聊天的SDK跟安卓同僚統一,最終選擇了環信。在官方下載下傳好SDK,并研究了一波,最終實作自定義聊天功能。 ###實作前準備 1.下載下傳環信SDK,我使用的版本是
V3.2.0 2016-10-15
,并且一開始我隻使用了簡版的,沒有實時語音視訊通訊,沒有支付寶紅包。基于環信實作實時語音視訊通話功能
2.在下載下傳的檔案夾中找到
HyphenateSDK
、
EaseUI
并在demo中找到
emotion
表情包,一起拖到新工程中。
3.向Build Phases → Link Binary With Libraries 中添加依賴庫。SDK 依賴庫有:
CoreMedia.framework
AudioToolbox.framework
AVFoundation.framework
MobileCoreServices.framework
ImageIO.framework
libc++.dylib
libz.dylib
libstdc++.6.0.9.dylib
libsqlite3.dylib
複制代碼
SDK 不支援 bitcode,向 Build Settings → Linking → Enable Bitcode 中設定 NO。在Build Settings-->Other Linker Flags-->輕按兩下 填寫上:-all_load
4.在工程中設定
EaseUI-Prefix.pch
的路徑。Build Settings-->Prefix Header 複制粘貼路徑。如果你工程中有.pch檔案,那麼就隻需要将
EaseUI-Prefix.pch
中的代碼複制進原有的pct檔案中就行。(我就隻複制了這些)
#define DEMO_CALL 1
#import <UIKit/UIKit.h>
#import <Availability.h>
#import <Foundation/Foundation.h>
#endif
複制代碼
5.在
AppDelegate.m
中配置環信SDK相關代碼。首先在環信背景注冊項目,并送出測試版的遠端推送證書anps,需要提供的是.p12檔案。(推送證書及p12相關,請自行百度)導入頭檔案
#import "EMSDK.h"
在
AppDelegate.m
中的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
方法中初始化環信相關配置。
//自動同意加好友.
BOOL accept = [[EMClient sharedClient].options isAutoAcceptFriendInvitation];
accept = YES;
//iOS8 注冊APNS
if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
[application registerForRemoteNotifications];
UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
[application registerUserNotificationSettings:settings];
}
else{
UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
}
//AppKey:注冊的AppKey,詳細見下面注釋。
//apnsCertName:推送證書名(不需要加字尾),詳細見下面注釋。
NSString *apnsCertName = nil;
#if DEBUG
apnsCertName = @"xxxx";//填寫自己的推送證書名字
#else
apnsCertName = @"XXXX";//同上
#endif
EMOptions *options = [EMOptions optionsWithAppkey:@"AppKey"];//填寫自己注冊的AppKey
options.apnsCertName = apnsCertName;//
[[EMClient sharedClient] initializeSDKWithOptions:options];
複制代碼
并加上如下代碼
#pragma mark - 擷取及上傳deviceToken
/*!
@method 系統方法
@abstract 系統方法,擷取deviceToken,并上傳環信
*/
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
[[EMClient sharedClient] bindDeviceToken:deviceToken];
}
/*!
@method 系統方法
@abstract 系統方法,擷取deviceToken 失敗
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"error -- %@",error);
}
#pragma mark - 進入前背景 (環信)
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[EMClient sharedClient] applicationDidEnterBackground:application];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[EMClient sharedClient] applicationWillEnterForeground:application];
}
複制代碼
具體的SDK導入過程也就這些,編譯一下,如果沒報錯,就導入成功了。有報錯也沒關系,找到報錯的地方,有時候就是頭檔案找不到,或者檔案重複。仔細看看,把不需要的删掉,出現了連接配接錯誤就複制百度。放緩心态,要相信SDK是一定能導入成功的。
這裡也把環信的官方文檔一并貼上
###分析需求(一) 我沒有用環信demo的UI,大部分是自定義的。因為我覺得自定義的好一些,别人做的再好,那也是别人根據自己的需求做的,不一定滿足我們的需求。項目工程不便上傳,是以我就根據功能點,一步步地往下寫。(根據功能點來,更友善自定義)
從上圖中可以看到需要做到的一些功能點有:頭像、名稱、會話清單、消息、消息發送的時間、未讀消息标記;還有一點就是會話清單能左劃删除。這六點中名稱跟頭像環信是不提供的,注冊過環信的都知道,它的ID是數字跟字母的組合,沒有像這樣顯示自定義名稱的。關于頭像,環信伺服器也是不提供存儲的。 ###實作相關功能(一) 1.登入或注冊環信賬号,擷取會話清單。(賬号密碼是按照我的項目來的,通過本地資料庫存儲好友資訊,對照着替換)首先導入頭檔案
#import "EMSDK.h"
、
#import "EaseUI.h"
/*!
@method 登入并加載會話清單。
@abstract 登入并加載會話清單。
*/
- (void)loginAndLoadData
{
//-----------------------登入邏輯----------------------//
FDAccountItem *item = [FDLoginTool fd_account];
NSString *psw = [item.key substringFromIndex:12];
NSLog(@"psw=%@==%@",psw,item.perName);
//---首先判斷能不能以該身份證為賬号進行登入----//
EMError *error = [[EMClient sharedClient] loginWithUsername:[item.key md5String] password:[psw md5String]];
if (!error) {
//設定遠端推送使用者名字
[[EMClient sharedClient] setApnsNickname:item.perName];
if (!error) {
NSLog(@"添加成功");
}
NSLog(@"登入成功");
//自動登入
[[EMClient sharedClient].options setIsAutoLogin:YES];
[MBProgressHUD hideHUD];
}
else
{
NSLog(@"%@", error);
//-------不能以該身份證号為賬号登入,就已該身份證号進行注冊-------//
EMError *regError = [[EMClient sharedClient]registerWithUsername:[item.key md5String] password:[psw md5String]];
if (regError ==nil) {
//-----注冊成功之後就進行登入-----//
EMError *logError = [[EMClient sharedClient] loginWithUsername:[item.key md5String] password:[psw md5String]];
if (!logError) {
//自動登入
[[EMClient sharedClient].options setIsAutoLogin:YES];
[MBProgressHUD hideHUD];
}
else
{
NSLog(@"登入失敗");
[MBProgressHUD hideHUD];
}
}
else
{
NSLog(@"error=%@",error);
[MBProgressHUD hideHUD];
}
}
//-------------------------end---------------------------//
//擷取所有會話
NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
self.dataArr = [[NSMutableArray alloc]initWithArray:conversations];
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];//聊天子產品注冊監聽
}
複制代碼
/*!
@method 環信方法,監聽收到消息
@abstract 不管app前台、背景,收到消息都會來到這個方法
*/
- (void)messagesDidReceive:(NSArray *)aMessages
{
[self getUnReadCountFromEM];
[self.tableView reloadData];
}
/*!
@method 從環信擷取所有的未讀消息
@abstract 從環信擷取所有的未讀消息
*/
- (NSInteger)getUnReadCountFromEM {
NSInteger unReadCount = 0;
// 擷取所有回話清單
NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
self.dataArr = [NSMutableArray arrayWithArray:conversations];
for (EMConversation *conversation in conversations) {
unReadCount += conversation.unreadMessagesCount;
}
if (unReadCount > 0) {
[self.tabBarController.tabBar huanX_showBadgeOnItemIndex:0];//自定義界面上顯示未讀消息小紅點
}
else
{
[self.tabBarController.tabBar fd_hideBadgeOnItemIndex:0];//同上
}
return unReadCount;
}
複制代碼
2.單元格cell界面的配置以及消息的處理。
XiaoXiTableViewCell *cell = [[[NSBundle mainBundle]loadNibNamed:@"XiaoXiTableViewCell" owner:nil options:nil]lastObject];
EMConversation *conversation = self.dataArr[indexPath.row];
int a = conversation.unreadMessagesCount;
if (a > 0) {
cell.hongDianImage.hidden = NO;
}else
{
cell.hongDianImage.hidden = YES;
}
//獲得最後一條消息
EMMessage *message = conversation.latestMessage;
//獲得消息體
EMMessageBody *messageBody = message.body;
NSString *str;
if (messageBody.type==EMMessageBodyTypeText) {
//消息為文本時,強轉為EMTextMessageBody 擷取文本消息
EMTextMessageBody *textBody =(EMTextMessageBody *)messageBody;
str = [EaseConvertToCommonEmoticonsHelper convertToSystemEmoticons:textBody.text];
//str = textBody.text;
}
//判斷消息類型,輸出響應類型
else if (messageBody.type==EMMessageBodyTypeImage)
{
str = @"[圖檔]";
}
else if (messageBody.type==EMMessageBodyTypeVoice)
{
str = @"[語音]";
}
else if (messageBody.type==EMMessageBodyTypeLocation)
{
str = @"[位置]";
}
else if (messageBody.type==EMMessageBodyTypeVideo)
{
str = @"[視訊]";
}
else if (messageBody.type==EMMessageBodyTypeFile)
{
str = @"[檔案]";
}
else
{
str = @"";
}
cell.xiaoXiLabel.text = str;
//-----------------end--------------------//
//找到會話
EaseConversationModel *model = [[EaseConversationModel alloc]initWithConversation:conversation];
//SaveHaoYouModel *haoYouModel = [HaoYouDao selectedFromPeopleTableWithMDsfz:model.title];
//設定消息時間
cell.timeLabel.text = [self timeStr:message.timestamp];
//設定消息發送者昵稱
// 打開資料庫
[HaoYouDao createYiShengTable];
// 搜尋名醫模型
SaveMingYiModel *mYModel = [HaoYouDao selectedFromPeopleTableWithMDsfz:model.title];
NSLog(@"ss%@----%@-",mYModel.docName,mYModel.idcardno);
cell.nameLabel.text = mYModel.docName;
NSString *imageUrl = [NSString stringWithFormat:@"https://219.140.163.100:2265/FDAPP/app_upload/%@.jpg",mYModel.idcardno];
[cell.headImage sd_setImageWithURL:[NSURL URLWithString:imageUrl]
placeholderImage:[UIImage imageNamed:@"touxiang"]];
//通過擴充消息獲得,該消息的擴充消息,即使用者的頭像,昵稱
//統一設定單元格分割線,和單元格選中樣式
cell.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
複制代碼
3.時間的處理。
/*!
@method 計算消息時間。
@abstract 計算接收到消息的時間,并判斷。
*/
- (NSString *)timeStr:(long long)timestamp
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *currentDate = [NSDate date];
// 擷取目前時間的年、月、日
NSDateComponents *components = [calendar components:NSCalendarUnitYear| NSCalendarUnitMonth|NSCalendarUnitDay fromDate:currentDate];
NSInteger currentYear = components.year;
NSInteger currentMonth = components.month;
NSInteger currentDay = components.day;
NSDate *msgDate = nil;
// 擷取消息發送時間的年、月、日
if (timestamp == 0) {
msgDate = currentDate;
} else {
msgDate = [NSDate dateWithTimeIntervalSince1970:timestamp/1000.0];
}
components = [calendar components:NSCalendarUnitYear| NSCalendarUnitMonth|NSCalendarUnitDay fromDate:msgDate];
CGFloat msgYear = components.year;
CGFloat msgMonth = components.month;
CGFloat msgDay = components.day;
// 判斷
NSDateFormatter *dateFmt = [[NSDateFormatter alloc] init];
if (currentYear == msgYear && currentMonth == msgMonth && currentDay == msgDay) {
//今天
dateFmt.dateFormat = @"HH:mm";
}else if (currentYear == msgYear && currentMonth == msgMonth && currentDay-1 == msgDay ){
//昨天
dateFmt.dateFormat = @"昨天 HH:mm";
}else{
//昨天以前
dateFmt.dateFormat = @"yyyy-MM-dd";
}
return [dateFmt stringFromDate:msgDate];
}
複制代碼
4.删除會話。
/*!
@method 開啟tableview删除功能。
@abstract 開啟tableview删除功能.
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// 删除會話
EMConversation *conversation = self.dataArr[indexPath.row];
[[EMClient sharedClient].chatManager deleteConversation:conversation.conversationId isDeleteMessages:YES completion:^(NSString *aConversationId, EMError *aError) {
}];
// 重新整理表
[self.dataArr removeObjectAtIndex:indexPath.row];
[self.tableView reloadData];
}
複制代碼
5.點選消息,與相應的id進行聊天。
//點選消息,與相應的id進行聊天
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//找到會話
EMConversation *conversation = self.dataArr[indexPath.row];
EaseConversationModel *model = [[EaseConversationModel alloc]initWithConversation:conversation];
//從本地資料庫中比對,找到好友資訊
SaveMingYiModel *mingYiModel = [HaoYouDao selectedFromPeopleTableWithMDsfz:model.title];
//model.title = haoYouModel.name;
EaseMessageViewController *viewController = [[EaseMessageViewController alloc] initWithConversationChatter:model.conversation.conversationId conversationType:model.conversation.type];
// viewController.title = model.title;
viewController.title = mingYiModel.docName;
[self.navigationController pushViewController:viewController animated:YES];
}
複制代碼
###分析需求(二)
這個界面的UI大部分都已經有了,需要改的是導航控制器标題、昵稱、頭像。 ###實作相關功能(二) 1.标題在上一個界面調用跳轉聊天控制器
EaseMessageViewController
的時候就已經傳過來了。
2.關于昵稱跟頭像,需要修改環信的消息擴充類。消息擴充類在發送各種消息的時候都要設定。(文字、語音、表情、圖檔、視訊)
最後需要用到的地方,在
EaseMessageViewController.m
的
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{}
方法的最後加上如下代碼:
如果URL中沒有頭像,就需要設定預設頭像。如下
需要注意的是,字典中值不能為空,要考慮各種情況,避免字典為空。還要注意的是,如果項目既有iOS版本,又有安卓版本,字典中鍵字元串需要保持一緻。使用者的昵稱是本地存的,頭像是我伺服器存的,URL也是我伺服器給的。 ###分析需求(三)
這個界面的需求就是擷取環信好友清單,并按首字母進行排序。昵稱跟頭像同樣需要自己處理。 ###實作相關功能(三) 1.擷取環信好友清單。
//------------------從環信伺服器擷取所有的好友 異步加載-------------------//
[[EMClient sharedClient].contactManager getContactsFromServerWithCompletion:^(NSArray *aList, EMError *aError) {
if (!aError) {
self.dataArr = [[NSMutableArray alloc]initWithArray:aList];
NSLog(@"haoyou==%ld",self.dataArr.count);
//-------主線程重新整理UI---------
[self performSelectorOnMainThread:@selector(refreshUI) withObject:nil waitUntilDone:YES];
}
}];
複制代碼
2.将擷取到的環信ID跟本地資料庫比對,擷取中文昵稱。
//1. 利用好友賬号在資料庫中檢索,好友模型
SaveMingYiModel *model = [[SaveMingYiModel alloc]init];
self.modelArr = [[NSMutableArray alloc]init];
for (NSString *str in self.dataArr) {
model = [HaoYouDao selectedFromPeopleTableWithMDsfz:str];
if (model) {
[self.modelArr addObject:model];
}
}
//2. 通過好友模型,輸出好友名字,并添加到數組中
NSLog(@"%ld",self.dataArr.count);
if (self.modelArr.count>0) {
NSMutableArray *arr = [[NSMutableArray alloc]init];
for (SaveMingYiModel *model in self.modelArr) {
NSString *name = model.docName;
if (name) {
[arr addObject:name];
}
}
//3. 将漢字轉換為拼音,并進行排序
self.indexArray = [ChineseString IndexArray:arr];
self.letterResultArr = [ChineseString LetterSortArray:arr];
[self.tableView reloadData];
複制代碼
關于按拼音首字母排序,需要導入兩個類檔案
ChineseString
、
pinyin
,網上可以搜到。需要的話也可以留郵箱,我發過去。下面貼上這個界面的全部代碼。有些是關于本地資料庫的類,關于資料庫的操作這裡不寫。
#import "HaoYouViewController.h"
#import "HaoYouTableViewCell.h"
#import "EMSDK.h"
#import "EaseUI.h"//環信相關
#import "ChineseString.h"//按照拼音首字母排序
#import "MyDoctorItem.h"//好友模型
#import "FDLoginTool.h"//登入工具類
#import "HaoYouDao.h"//資料庫DAO類
#import "SaveMingYiModel.h"//資料庫相關的好友模型
#define APP_WIDTH [[UIScreen mainScreen]applicationFrame].size.width
#define APP_HEIGHT [[UIScreen mainScreen]applicationFrame].size.height
@interface HaoYouViewController ()<UITableViewDelegate,UITableViewDataSource,EMChatManagerDelegate,EMContactManagerDelegate>
@property (nonatomic,strong) UITableView *tableView;
@property (nonatomic,strong) NSMutableArray *dataArr;
@property (nonatomic,strong) NSMutableArray *modelArr;
@property (nonatomic,strong) NSMutableArray *indexArray;
@property (nonatomic,strong) NSMutableArray *letterResultArr;
@property (nonatomic,strong) UILabel *sectionTitleView;
@property (nonatomic,strong) NSTimer *timer;
@end
@implementation HaoYouViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"醫生清單";
self.view.backgroundColor = kGlobalBackgroundColor;
// 打開資料庫
[HaoYouDao createYiShengTable];
// 建立表
self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, kScreenW, kScreenH) style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.rowHeight = 65;
[self.view addSubview:_tableView];
//去掉多餘的分割線
self.tableView.tableFooterView = [[UIView alloc]init];
//改變索引字的顔色,索引背景的顔色
self.tableView.sectionIndexColor =[UIColor colorWithRed:153/255.0 green:153/255.0 blue:153/255.0 alpha:1];
self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];
//------------------從環信伺服器擷取所有的好友 異步加載-------------------//
[[EMClient sharedClient].contactManager getContactsFromServerWithCompletion:^(NSArray *aList, EMError *aError) {
if (!aError) {
self.dataArr = [[NSMutableArray alloc]initWithArray:aList];
NSLog(@"haoyou==%ld",self.dataArr.count);
//-------主線程重新整理UI---------
[self performSelectorOnMainThread:@selector(refreshUI) withObject:nil waitUntilDone:YES];
}
}];
}
/*!
@method 重新整理UI。
@abstract 加載好友清單,按首字母排序.
*/
- (void)refreshUI
{
self.sectionTitleView = ({
UILabel *sectionTitleView = [[UILabel alloc] initWithFrame:CGRectMake((APP_WIDTH-100)/2, (APP_HEIGHT-100)/2,100,100)];
sectionTitleView.textAlignment = NSTextAlignmentCenter;
sectionTitleView.font = [UIFont boldSystemFontOfSize:60];
sectionTitleView.textColor = [UIColor grayColor];
sectionTitleView.backgroundColor = [UIColor whiteColor];
sectionTitleView.layer.cornerRadius = 6;
sectionTitleView.layer.masksToBounds = YES;
sectionTitleView.layer.borderWidth = 1.f/[UIScreen mainScreen].scale;
_sectionTitleView.layer.borderColor = [UIColor groupTableViewBackgroundColor].CGColor;
sectionTitleView;
});
[self.navigationController.view addSubview:self.sectionTitleView];
self.sectionTitleView.hidden = YES;
//1. 利用好友賬号在資料庫中檢索,好友模型
SaveMingYiModel *model = [[SaveMingYiModel alloc]init];
self.modelArr = [[NSMutableArray alloc]init];
for (NSString *str in self.dataArr) {
model = [HaoYouDao selectedFromPeopleTableWithMDsfz:str];
if (model) {
[self.modelArr addObject:model];
}
}
//2. 通過好友模型,輸出好友名字,并添加到數組中
NSLog(@"%ld",self.dataArr.count);
if (self.modelArr.count>0) {
NSMutableArray *arr = [[NSMutableArray alloc]init];
for (SaveMingYiModel *model in self.modelArr) {
NSString *name = model.docName;
if (name) {
[arr addObject:name];
}
}
//3. 将漢字轉換為拼音,并進行排序
self.indexArray = [ChineseString IndexArray:arr];
self.letterResultArr = [ChineseString LetterSortArray:arr];
[self.tableView reloadData];
}
}
//------------------tableview 的delegate,dataSource 方法--------------//
// 傳回區頭索引數組
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.indexArray;
}
// 傳回區頭标題
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *key = [self.indexArray objectAtIndex:section];
return key;
}
// 傳回區個數
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.indexArray count];
}
// 傳回每區的行數
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.letterResultArr objectAtIndex:section] count];
}
// 配置單元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HaoYouTableViewCell *cell = [[[NSBundle mainBundle]loadNibNamed:@"HaoYouTableViewCell" owner:nil options:nil]lastObject];
cell.nameLabel.text = [[self.letterResultArr objectAtIndex:indexPath.section]objectAtIndex:indexPath.row];
SaveMingYiModel *model = [HaoYouDao selectedFromPeopleTableWithName:[[self.letterResultArr objectAtIndex:indexPath.section]objectAtIndex:indexPath.row]];
//将小寫x轉換為大寫X
NSString *upStr = [model.idcardno uppercaseString];
NSLog(@"sss=%@",upStr);
//拼接頭像URL位址
NSString *imgUrl = [@"https://219.140.163.100:2265/FDAPP/app_upload/" stringByAppendingFormat:@"%@.jpg",upStr];
[cell.headImage sd_setImageWithURL:[NSURL URLWithString:imgUrl] placeholderImage:[UIImage imageNamed:@"touxiang.png"]];
//統一設定單元格分割線,和單元格選中樣式
cell.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
// 設定行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.indexArray.count>0) {
return 50;
}
else
{
return kScreenH - 64;
}
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
[self showSectionTitle:title];
return index;
}
#pragma mark - private
- (void)timerHandler:(NSTimer *)sender
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:.3 animations:^{
self.sectionTitleView.alpha = 0;
} completion:^(BOOL finished) {
self.sectionTitleView.hidden = YES;
}];
});
}
-(void)showSectionTitle:(NSString*)title{
[self.sectionTitleView setText:title];
self.sectionTitleView.hidden = NO;
self.sectionTitleView.alpha = 1;
[self.timer invalidate];
self.timer = nil;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerHandler:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
#pragma mark - UITableViewDelegate
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 25)];
headerView.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1];
UILabel *lab = [[UILabel alloc]initWithFrame:CGRectMake(10, 0, 40, 25)];
lab.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1];
lab.font = [UIFont systemFontOfSize:12];
lab.text = [self.indexArray objectAtIndex:section];
lab.textColor = [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1];
[headerView addSubview:lab];
return headerView;
}
// 點選好友,進入詳情界面
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 找到好友模型
SaveMingYiModel *model = [HaoYouDao selectedFromPeopleTableWithName:[[self.letterResultArr objectAtIndex:indexPath.section]objectAtIndex:indexPath.row]];
// 根據好友的身份證MD5 跳轉聊天界面
EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:model.sfzMD5 conversationType:EMConversationTypeChat];
// 隐藏底部tabBar
chatController.hidesBottomBarWhenPushed = YES;
// 聊天标題
chatController.title = model.docName;
[self.navigationController pushViewController:chatController animated:YES];
}
// 設定區頭區尾高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 25;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.01;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tabBarController.title = @"醫生清單";
}
複制代碼
至此,聊天功能大部分寫完,下面貼一張本地資料庫的圖。
環信ID要的是數字跟字母,是以在項目中,我就用身份證MD5加密作為環信的ID,資料庫中每條好友資訊都是從伺服器中請求的,存入資料庫,友善通過mdSfz(也就是通過環信請求到的好友ID)這個字段去資料庫檢索資訊。 ###最後說一下消息推送部分 1.遠端推送。之前在AppDelegate中的設定如果沒有什麼問題,并且推送證書 p12檔案都是正确的話,(p12檔案要上傳到環信背景)遠端推送就沒有任何問題。
2.本地推送。在
MainViewController.m
中處理,(進入程式的第一個視圖控制器)首先導入頭檔案
EaseSDKHelper.h
在
viewDidLoad
中注冊聊天子產品監聽
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
然後寫入如下代碼:
/*!
@method 環信方法,監聽收到消息
@abstract 不管app前台、背景,收到消息都會來到這個方法
*/
- (void)messagesDidReceive:(NSArray *)aMessages
{
// 前台就不跳轉
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
// 震動
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
EMMessage *message = aMessages[0];
//獲得消息體
EMMessageBody *messageBody = message.body;
NSString *str;
if (messageBody.type==EMMessageBodyTypeText) {
//消息為文本時,強轉為EMTextMessageBody 擷取文本消息
EMTextMessageBody *textBody =(EMTextMessageBody *)messageBody;
str = textBody.text;
}
//判斷消息類型,輸出相應類型
else if (messageBody.type==EMMessageBodyTypeImage)
{
str = @"[圖檔]";
}
else if (messageBody.type==EMMessageBodyTypeVoice)
{
str = @"[語音]";
}
else if (messageBody.type==EMMessageBodyTypeLocation)
{
str = @"[位置]";
}
else if (messageBody.type==EMMessageBodyTypeVideo)
{
str = @"[視訊]";
}
else if (messageBody.type==EMMessageBodyTypeFile)
{
str = @"[檔案]";
}
else
{
str = @"";
}
//message.ext[@"img"];//頭像
//message.ext[@"accountName"];//昵稱
NSString *notifyMessage = [NSString stringWithFormat:@"%@:%@",message.ext[@"accountName"],str];
NSLog(@"notifyMessage%@",notifyMessage);
UILocalNotification *notify = [[UILocalNotification alloc]init];
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
notify.fireDate = fireDate;
//時區
notify.timeZone = [NSTimeZone defaultTimeZone];
//通知内容
notify.alertBody = notifyMessage;
//通知被觸發時播放的聲音
notify.soundName = UILocalNotificationDefaultSoundName;
//通知參數
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:message.ext[@"accountName"],@"好友",@(badgeNum),@"badgeNum",nil];
notify.userInfo = dic;
// ios8後,需要添加這個注冊,才能得到授權
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type
categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 執行通知注冊
[[UIApplication sharedApplication] scheduleLocalNotification:notify];
});
}
}
複制代碼
本地通知發送完成,若需要本地通知相關資訊,需要在
AppDelegate.m
中接收本地通知并處理。
基于環信實作實時語音視訊通話功能
轉載請注明出處 © XDChang
轉載于:https://juejin.im/post/5b4421c46fb9a04fa42f9b59