1.網(wǎng)易云信
網(wǎng)易云信算是國(guó)內(nèi)比較老牌的IM即時(shí)通訊服務(wù)商了棍鳖,公司項(xiàng)目里集成的網(wǎng)易云信SDK汁针,關(guān)于這個(gè)SDK就不多說(shuō)了,官網(wǎng)上的介紹比較詳細(xì)津辩。
項(xiàng)目里接入了SDK拆撼,然后UI界面是使用的網(wǎng)易提供的一套UI框架容劳,叫NIMKit.h
在此基礎(chǔ)上進(jìn)行開(kāi)發(fā)。
2.IM已讀回執(zhí)
IM已讀回執(zhí)闸度,整個(gè)的過(guò)程簡(jiǎn)單說(shuō)來(lái)就是:
1.聊天消息的發(fā)送方竭贩,發(fā)出的一條帶開(kāi)通回執(zhí)功能的消息(可以是文字,圖片等等莺禁,語(yǔ)音一般都自帶回執(zhí))留量;
2.聊天接收方查看了(前提是收到了該消息)了這條消息,要告訴發(fā)送方我我已經(jīng)查看了哟冬,此時(shí)發(fā)一條該消息已讀的指令給發(fā)送方楼熄;
3.聊天發(fā)送方,收到接收方浩峡,發(fā)來(lái)的消息已讀回執(zhí)可岂。這個(gè)時(shí)候,就要更新本地?cái)?shù)據(jù)翰灾,在UI界面上把那條聊天信息缕粹,顯示為已讀;
群聊也是如此纸淮,在群聊中發(fā)出一條消息平斩,通過(guò)回執(zhí)功能可以看出誰(shuí)已讀或者未讀。
如果你用過(guò)釘釘咽块,就很好理解這個(gè)流程绘面。
3.前期準(zhǔn)備
既然是迭代開(kāi)發(fā),沒(méi)玩過(guò)這個(gè)SDK肯定是要查看開(kāi)發(fā)文檔的糜芳。
NIMKit文檔
單聊文檔
群聊文檔
敲黑板飒货,劃重點(diǎn),要考G涂ⅰ!
網(wǎng)易云信SDK晃虫,已讀回執(zhí)功能皆撩,需要單獨(dú)開(kāi)通服務(wù),而且是付費(fèi)服務(wù)
也就是說(shuō)哲银,代碼寫(xiě)的再好扛吞,不花錢(qián)開(kāi)通也沒(méi)吊用。
講到這里荆责,其實(shí)最最首要的任務(wù)是:充錢(qián)滥比,充錢(qián),充錢(qián)做院!
4.拿起鍵盤(pán)就是干
4.1 聊天Cell定制
如下圖盲泛,NIMKit里面已經(jīng)封裝好了一套聊天Cell濒持。根據(jù)業(yè)務(wù)需要自行調(diào)整。
比如寺滚,它的readLabel是放在最左側(cè)柑营,我們需求是放在底部位置。所以自行重定義布局村视,很簡(jiǎn)單代碼就不貼了官套。
當(dāng)然NIMKitConfig里面你要自定義好readLabel的字體大小顏色,內(nèi)容等等蚁孔。
NIMMessageModel是每一條聊天消息的model實(shí)體奶赔,readlabel的隱藏顯示是由shouldShowReadLabel這個(gè)屬性來(lái)驅(qū)動(dòng)。
NIMSessionTableAdapter這個(gè)類(lèi)用來(lái)負(fù)責(zé)聊天頁(yè)面的tableview相關(guān)杠氢,因?yàn)樾枨笫菍⒁炎x放到了消息底部纺阔,那必然要對(duì)cell的高度進(jìn)行調(diào)整。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat cellHeight = 0;
id modelInArray = [[self.interactor items] objectAtIndex:indexPath.row];
if ([modelInArray isKindOfClass:[NIMMessageModel class]]) {
NIMMessageModel *model = (NIMMessageModel *)modelInArray;
CGSize size = [model contentSize:tableView.nim_width];
UIEdgeInsets contentViewInsets = model.contentViewInsets;
UIEdgeInsets bubbleViewInsets = model.bubbleViewInsets;
CGFloat unreadLabelHeight = [model.message.from isEqualToString:[NIMSDK sharedSDK].loginManager.currentAccount] ? 20 : 0;// 高度適配
cellHeight = size.height + contentViewInsets.top + contentViewInsets.bottom + bubbleViewInsets.top + bubbleViewInsets.bottom + unreadLabelHeight;
}
....
}
4.2 P2P聊天
P2P就是點(diǎn)對(duì)點(diǎn)聊天修然,就是單聊笛钝。
在會(huì)話界面中調(diào)用發(fā)送已讀回執(zhí)的接口并傳入最后一條消息,即表示這之前的消息都已讀愕宋,對(duì)端將收到此回執(zhí)玻靡。
發(fā)送已讀回執(zhí)
@protocol NIMChatManager <NSObject>
- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
completion:(NIMSendMessageReceiptBlock)completion;
@end
接受已讀回執(zhí)
@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessageReceipts:(NSArray<NIMMessageReceipt *> *)receipts;
@end
文檔里說(shuō)了這些,所有只要在生命周期方法里中贝,把最后一條消息撈出來(lái)囤捻,調(diào)一下sendMessageReceipt方法即可。
如果發(fā)送了回執(zhí)邻寿,對(duì)方的onRecvMessageReceipts就會(huì)被調(diào)用蝎土。網(wǎng)易牛逼的地方就是,收到回執(zhí)的時(shí)候绣否,SDK內(nèi)部已經(jīng)把數(shù)據(jù)都處理好了誊涯,上層只需要把UI刷新一下即可。
什么蒜撮?你問(wèn)我怎么刷新暴构??
在onRecvMessageReceipts里[self.tableView reloadData];
爽不爽段磨?
4.3 群聊發(fā)送已讀回執(zhí)
群聊和單聊方法基本差不多取逾,但是要改一個(gè)屬性,
發(fā)送需要標(biāo)記已讀回執(zhí)的群組消息標(biāo)記
/**
* 其他群成員收到此消息是否需要發(fā)送已讀回執(zhí)
* @discussion 默認(rèn)為NO苹支,設(shè)置成 YES 之后所有群回執(zhí)相關(guān)操作才會(huì)生效
*/
@property (nonatomic,assign) BOOL teamReceiptEnabled;
一句話搞定
[NIMSDKConfig sharedConfig].teamReceiptEnabled = YES;
消息接收方收到消息砾隅,并回復(fù)回執(zhí) 在會(huì)話界面中調(diào)用發(fā)送已讀回執(zhí)的接口并傳入最后一條消息,即表示這之前的消息都已讀债蜜,對(duì)端將收到此回執(zhí)晴埂。
@protocol NIMChatManager <NSObject>
- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
completion:(NIMSendMessageReceiptBlock)completion;
@end
到這里就遇到坑了究反,屬性都配置好了,發(fā)回執(zhí)就是不行邑时。后來(lái)咨詢了網(wǎng)易的技術(shù)支持奴紧,他丟給了我一個(gè)鏈接https://faq.yunxin.163.com/kb/main/#/item/KB0335。
原來(lái)網(wǎng)易還有知識(shí)寶庫(kù)這玩意
原來(lái)不只是要將NIMSDKConfig的teamReceiptEnabled要改成YES晶丘,NIMMessage中的setting中的teamReceiptEnabled也要改成YES黍氮,這個(gè)文檔里居然沒(méi)寫(xiě)。要不是技術(shù)支持發(fā)給我誰(shuí)知道有這玩意浅浮?沫浆??
#pragma mark - NIMChatManagerDelegate
- (void)willSendMessage:(NIMMessage *)message {
id<NIMSessionInteractor> interactor = self.interactor;
if (message.session.sessionType == NIMSessionTypeTeam) {
message.setting.teamReceiptEnabled = YES; // 設(shè)置里打開(kāi)才行滚秩。
}
....
}
這樣之后才能正確發(fā)送已讀回執(zhí)专执。
發(fā)送已讀回執(zhí)之后,對(duì)方的那條消息郁油,就能看到
model.message.teamReceiptInfo.unreadCount
就能再UI上顯示多少人未讀本股。
4.4 群聊查看消息已讀未讀列表
SDK里面已提供了查詢消息已讀id列表接口
查詢?cè)斍榻涌?br>
包括已讀人數(shù)的 id 和 未讀人數(shù)的 id 列表。需要注意查詢?cè)斍閷?duì)象不會(huì)跟著回執(zhí)人數(shù)變化而變化桐腌,如果要獲取最新的詳情拄显,必須再次調(diào)用此接口。
@protocol NIMChatManagerDelegate <NSObject>
/**
* 查詢?nèi)航M消息回執(zhí)詳情
*
* @param NIMMessage 要查詢的消息
* @discussion 詳情包括已讀人數(shù)的 id 列表和未讀人數(shù)的 id 列表
* 查詢?cè)斍閷?duì)象不會(huì)跟著回執(zhí)人數(shù)變化而變化案站,如果要獲取最新的詳情躬审,必須再次調(diào)用此接口
*
*/
- (void)queryMessageReceiptDetail:(NIMMessage *)message
completion:(NIMQueryReceiptDetailBlock)completion;
@end
參數(shù)正確之后,會(huì)返回這條消息的已讀id列表和未讀id列表蟆盐,列表里面保存的是userid承边。
這里也遇到一個(gè)坑:
在聊天界面,當(dāng)前新發(fā)送的消息石挂,能夠查詢到已讀未讀列表博助。但是打開(kāi)頁(yè)面之前的歷史消息,無(wú)論如何都查不到誊稚。
經(jīng)過(guò)debug發(fā)現(xiàn)翔始,當(dāng)退出聊天窗口,所有的消息變成歷史數(shù)據(jù)之后里伯,才進(jìn)入聊天窗口,所有的歷史消息message.setting.teamReceiptEnabled
統(tǒng)統(tǒng)變成了NO渤闷,解決方法也很簡(jiǎn)單疾瓮,每次queryMessageReceiptDetail
查詢之前,再把這個(gè)屬性設(shè)置成YES就能正確查詢列表了飒箭。
注意點(diǎn):網(wǎng)易云信最多支持100人群聊的已讀消息回執(zhí)
超過(guò)100也就不支持了狼电,如果不能滿足需求蜒灰,要么有本事自己寫(xiě)一套IM,要么就換一家SDK吧肩碟。
5.結(jié)束語(yǔ)
雖然是第一次接觸强窖,總體覺(jué)得網(wǎng)易這整個(gè)一套IM的SDK也不是很難,嵌套的比較多削祈,需要認(rèn)真梳理各個(gè)類(lèi)各個(gè)協(xié)議翅溺,所承載的功能。其次髓抑,開(kāi)發(fā)難免會(huì)遇到一些坑和彎路咙崎,寫(xiě)這篇文章也算是為了幫后來(lái)人吧。
如有錯(cuò)誤吨拍,還請(qǐng)各位看官批評(píng)指正~