云信用戶信息獲取
云信提供的方式有兩種 服務器同步信息 和 客戶端同步信息,雖然云信推薦使用 服務器同步信息 方式,但是抱歉我們的產(chǎn)品不是這樣做的,而是需要我們客戶端儲存用戶信息進行維護資料。
在使用NIMKit中,涉及到會話列表,聊天頁面,以及自定義聊天頁面的設(shè)計,根據(jù)云信的設(shè)計中,只要有userId(我們項目中定義是叫做chatAccount,以下都稱作userId),就能直接獲取到用戶信息,但是直接獲取的話是獲取到的云信維護的用戶信息([NIMKit sharedKit].provider通過這個對象獲取用戶信息),但是我們的用戶信息不依賴云信而是由我們自己維護,所以在聊天頁面和會話列表顯示出來的頭像和名稱有可能與我們自己需要的頭像和名字不一致,在剛剛開始使用云信的NIMSDK的時候也確實糾結(jié)了一會,后來翻閱云信在guthub上的文檔發(fā)現(xiàn)了,實際上我們只要有一個類實現(xiàn)了
NIMKitDataProvider協(xié)議以及NIMKitDataProviderImpl類,并且在Appdelegate中像NIMSDK注冊,就能夠?qū)崿F(xiàn)自定義的用戶信息的獲取了。
創(chuàng)建一個對象
PGDataProviderImpl集成自NIMKitDataProviderImpl重寫
NIMKitDataProvider協(xié)議中的方法,-
/** * 上層提供用戶信息的接口 * * @param userId 用戶ID * @param option 獲取選項 * * @return 用戶信息 */ - (NIMKitInfo *)infoByUser:(NSString *)userId option:(NIMKitInfoFetchOption *)option; /** * 上層提供群組信息的接口 * * @param teamId 群組ID * @param option 獲取選項 * * @return 群組信息 */ - (NIMKitInfo *)infoByTeam:(NSString *)teamId option:(NIMKitInfoFetchOption *)option;我在早期實現(xiàn)這些方法的方式是
- 先通過userId從我本地的數(shù)據(jù)庫中獲取資料
- 獲取本地數(shù)據(jù)庫數(shù)據(jù)成功則返回對應的數(shù)據(jù)
- 但是一旦本地數(shù)據(jù)庫沒有,則返回云信默認的數(shù)據(jù)(畢竟云信默認的數(shù)據(jù)是創(chuàng)建云信賬號時的原始數(shù)據(jù),等于是我們用戶的初始數(shù)據(jù),)同時向服務端獲取最新的數(shù)據(jù),且刷新界面。
- 這是我一開始的解決方案,但是體驗上感覺不好。
后來修改了數(shù)據(jù)獲取的策略,
- 每條發(fā)送的消息中都會包含一條ext數(shù)據(jù),這里包含了發(fā)送者的頭像名稱的相關(guān)需要的數(shù)據(jù)。ps.群聊消息則還會包含群聊的資料以及當前發(fā)送者在當前群聊中的群昵稱以及其他相關(guān)資料。
- 接收消息方會將本條消息中的有效數(shù)據(jù)暫時放在數(shù)據(jù)庫中
- 實現(xiàn)
NIMKitDataProvider協(xié)議 - 先通過userId從我本地的數(shù)據(jù)庫中獲取資料
- 獲取本地數(shù)據(jù)庫數(shù)據(jù)成功則返回對應的數(shù)據(jù)
- 但是一旦本地數(shù)據(jù)庫沒有,則優(yōu)先返回接收的消息中緩存的用戶資料,并且同時向自己的服務器獲取完整的用戶資料數(shù)據(jù)
- 這樣的話,體驗上會好很多,不會出現(xiàn)前后顯示不一致的情況了
3.在Appdelegate中,云信SDK注冊方法之后寫上[NIMKit sharedKit].provider = [[PGDataProviderImpl alloc]init];,以后在重寫會話列表,聊天列表和群聊資料時獲取到的資料就是我們需要的數(shù)據(jù)了。
自定義消息的實現(xiàn)
-
自定義消息模型 以及 發(fā)送自定義消息
- 創(chuàng)建模型 實現(xiàn)
NIMCustomAttachment協(xié)議,主要是實現(xiàn)- (NSString *)encodeAttachment;方法,才能使云信sdk將這條自定義的消息進行序列化,如果附帶其它的附件消息,實現(xiàn)對應的協(xié)議方法即可。 - 發(fā)送自定義消息和正常的發(fā)送消息沒有區(qū)別,別忘了
NIMCustomObject這個對象包含自定義消息模型就好了
- 創(chuàng)建模型 實現(xiàn)
-
接收自定義消息
- 創(chuàng)建對象
PGAttachmentDecoder并且實現(xiàn)NIMCustomAttachmentCoding協(xié)議,幫助云信實現(xiàn)自定義消息模型的反序列化。即實現(xiàn)- (id<NIMCustomAttachment>)decodeAttachment:(NSString *)content,content是上面encodeAttachment序列化出來的json數(shù)據(jù)。
- 創(chuàng)建對象
```
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[NIMCustomObject registerCustomDecoder:[[AttachmentDecoder alloc]init]];
...
}
```
自定義消息cell
-
新建氣泡內(nèi)容
氣泡內(nèi)容類需要繼承 NIMSessionMessageContentView ,并使用- (instancetype)initSessionMessageContentView作為初始化方法。內(nèi)容里根據(jù)業(yè)務需求自行排版。- 至于內(nèi)部到底怎么寫,可以參考云信提供的Demo。
- 整個cell能自定義的部分也只有這個contentView,但是實際可以將這個氣泡完全填充整個cell,也就變相的實現(xiàn)了整個cell的自定義
-
新建自定義消息氣泡布局配置,配置需要實現(xiàn)
NIMCellLayoutConfig協(xié)議。這里除自定義消息外,其他消息沿用內(nèi)置配置,所以配置類繼承基類NIMCellLayoutConfig。以下是云信官方提供的demo@interface CellLayoutConfig : NIMCellLayoutConfig<NIMCellLayoutConfig> @end@implementation CellLayoutConfig - (CGSize)contentSize:(NIMMessageModel *)model cellWidth:(CGFloat)width{ //填入內(nèi)容大小 if ([self isSupportedCustomModel:model]) { //先判斷是否是需要處理的自定義消息 return CGSizeMake(200, 50); } //如果不是自己定義的消息,就走內(nèi)置處理流程 return [super contentSize:model cellWidth:width]; } - (NSString *)cellContent:(NIMMessageModel *)model{ //填入contentView類型 if ([self isSupportedCustomModel:model]) { //先判斷是否是需要處理的自定義消息 return @"ContentView"; } //如果不是自己定義的消息,就走內(nèi)置處理流程 return [super cellContent:model]; } - (UIEdgeInsets)cellInsets:(NIMMessageModel *)model{ //填入氣泡距cell的邊距,選填 if ([self isSupportedCustomModel:model]) { //先判斷是否是需要處理的自定義消息 return UIEdgeInsetsMake(5, 5, 5, 5); } //如果不是自己定義的消息,就走內(nèi)置處理流程 return [super cellInsets:model]; } - (UIEdgeInsets)contentViewInsets:(NIMMessageModel *)model{ //填入內(nèi)容距氣泡的邊距,選填 if ([self isSupportedCustomModel:model]) { //先判斷是否是需要處理的自定義消息 return UIEdgeInsetsMake(5, 5, 5, 5); } //如果不是自己定義的消息,就走內(nèi)置處理流程 return [super contentViewInsets:model]; } @end -
將創(chuàng)建好的布局配置類注入到組件中,保證在會話頁實例化之前注入即可。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... //注冊 NIMKit 自定義排版配置 [[NIMKit sharedKit] registerLayoutConfig:[CellLayoutConfig new]]; ... }