项目中涉及到即时通讯模块、使用了融云的框架、前两天开始做到头像昵称设置、起初按照文档去做但是就是显示不正常、后来仔细研究才发现又走到坑里了、今天就系统的说一下其中遇到的问题吧。
首先我们来看看融云的开发文档中的描述
屏幕快照 2016-12-26 10.20.14.png
// RCIM Class
/*!
用户信息提供者
@discussion SDK需要通过您实现的用户信息提供者,获取用户信息并显示。
*/
@protocol RCIMUserInfoDataSource <NSObject>
/*!
获取用户信息
@param userId 用户ID
@param completion 获取用户信息完成之后需要执行的Block
@param userInfo(in completion) 该用户ID对应的用户信息
@discussion SDK通过此方法获取用户信息并显示,请在completion中返回该用户ID对应的用户信息。
在您设置了用户信息提供者之后,SDK在需要显示用户信息的时候,会调用此方法,向您请求用户信息用于显示。
*/
- (void)getUserInfoWithUserId:(NSString *)userId
completion:(void (^)(RCUserInfo *userInfo))completion;
@end
/*!
群组信息提供者
@discussion SDK需要通过您实现的群组信息提供者,获取群组信息并显示。
*/
@protocol RCIMGroupInfoDataSource <NSObject>
/*!
获取群组信息
@param groupId 群组ID
@param completion 获取群组信息完成之后需要执行的Block
@param groupInfo(in completion) 该群组ID对应的群组信息
@discussion SDK通过此方法获取用户信息并显示,请在completion的block中返回该用户ID对应的用户信息。
在您设置了用户信息提供者之后,SDK在需要显示用户信息的时候,会调用此方法,向您请求用户信息用于显示。
*/
- (void)getGroupInfoWithGroupId:(NSString *)groupId
completion:(void (^)(RCGroup *groupInfo))completion;
@end
/*!
用户信息提供者
@discussion SDK需要通过您实现的用户信息提供者,获取用户信息并显示。
*/
@property(nonatomic, weak) id<RCIMUserInfoDataSource> userInfoDataSource;
/*!
群组信息提供者
@discussion SDK需要通过您实现的群组信息提供者,获取群组信息并显示。
*/
@property(nonatomic, weak) id<RCIMGroupInfoDataSource> groupInfoDataSource;
屏幕快照 2016-12-26 10.19.57.png
是不是觉得自己已经秒懂、OK、来自己动手做一做、有没有感觉有坑了、哈哈、有坑就对了
接下来说说具体的做法:
实际上融云在针对头像昵称设置这块有两种处理方法、当然、也正是因为有两种方法、才会让我们一不小心就被自己坑、好了、我们分别来具体的看看到底有什么区别吧
PlanA:使用消息携带用户信息
这种方式会在每条发送的消息里都携带当前登陆用户的信息,增加消息的长度。
iOS端:
// 设置当前用户信息
[RCIM sharedRCIM].currentUserInfo = [[RCUserInfo alloc] initWithUserId:@"当前登录用户的融云id" name:@"当前登录用户的用户名" portrait:@"用户头像的url"];
// 设置消息体内是否携带用户信息
[RCIM sharedRCIM].enableMessageAttachUserInfo = YES;
/*!
是否在发送的所有消息中携带当前登录的用户信息,默认值为NO
@discussion 如果设置为YES,则会在每一条发送的消息中携带当前登录用户的用户信息。
收到一条携带了用户信息的消息,SDK会将其信息加入用户信息的cache中并显示;
若消息中不携带用户信息,则仍然会通过用户信息提供者获取用户信息进行显示。
@warning 需要先设置当前登录用户的用户信息,参考RCIM的currentUserInfo。
*/
@property(nonatomic, assign) BOOL enableMessageAttachUserInfo;
Android端:
/**
* 设置当前用户信息,
*
* @param userInfo 当前用户信息
*/
RongIM.getInstance().setCurrentUserInfo(userInfo);
接下来,在 init 之后调用下面方法设置消息携带用户信息。
/**
* 设置消息体内是否携带用户信息。
*
* @param state 是否携带用户信息,true 携带,false 不携带。
*/
RongIM.getInstance().setMessageAttachedUserInfo(true);
接收方在接收到消息后,SDK 会自动从消息中取出用户信息,并显示到 UI 上
以上所述为第一种设置方式,可以看出其实这种方式比较不好的一点就是会在每条消息中都携带用户的个人信息,造成大量的冗余,所以并不是特别推荐的方法。
需要注意的是,如果 安卓端 使用这种方式跟 iOS 互通时,需要 iOS 侧也在消息里携带用户信息,这样才能在两侧都正常显示昵称和头像。
另外,在测试过程中发现,iOS中使用这种方式时会出现一个问题就是:如果你给朋友发消息,发完以后在会话列表页面,对方如果没有回复的话,是显示不出来对方的头像和昵称的,只有对方看到消息回复后才会正常显示,所以说这个也算是一个bug吧。
因此,现在我们来看看第二种方案吧。
PlanB:设置用户信息提供者
iOS端:
首先遵守协议:RCIMUserInfoDataSource,RCIMGroupInfoDataSource
在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中 设置代理:
[[RCIM sharedRCIM] setUserInfoDataSource:self];
[[RCIM sharedRCIM] setGroupInfoDataSource:self];
实现代理方法,以个人信息为例:
- (void)getUserInfoWithUserId:(NSString *)userId
completion:(void (^)(RCUserInfo *userInfo))completion
{
if ([userId isEqualToString:@"当前登录用户的融云id"]) {
return completion([[RCUserInfo alloc] initWithUserId:userId name:@"当前登录用户的用户名" portrait:@"当前登录用户头像的url"]);
}else
{
根据存储联系人信息的模型,通过 userId 来取得对应的name和头像url,进行以下设置(此处因为项目接口尚未实现,所以就只能这样给大家说说,请见谅)
return completion([[RCUserInfo alloc] initWithUserId:userId name:@"name" portrait:@"http://pic32.nipic.com/20130827/12906030_123121414000_2.png"]);
}
}
// 从 2.6.0 开始 IMKit 可以缓存用户信息到数据库里,开发者可以开启 RCIM.h 里的enablePersistentUserInfoCache (当然也可以不用写这个,个人感觉没有什么显著的用处)
[RCIM sharedRCIM].enablePersistentUserInfoCache = YES;
/*!
获取群组信息
@param groupId 群组ID
@param completion 获取群组信息完成之后需要执行的Block
@param groupInfo(in completion) 该群组ID对应的群组信息
@discussion SDK通过此方法获取用户信息并显示,请在completion的block中返回该用户ID对应的用户信息。
在您设置了用户信息提供者之后,SDK在需要显示用户信息的时候,会调用此方法,向您请求用户信息用于显示。
*/
- (void)getGroupInfoWithGroupId:(NSString *)groupId
completion:(void (^)(RCGroup *groupInfo))completion
{
// 此处做相应的群组设置即可,获取群组信息的流程与获取用户信息的流程一致
}
刷新 SDK 缓存
当用户信息或者群组信息发生变化之后,可以调用 RCIM 中的 -refreshUserInfoCache:withUserId: 或 -refreshGroupInfoCache:withGroupId: 方法通知 IMKit 更新缓存
//RCIM Class
/*!
更新SDK中的用户信息缓存
@param userInfo 需要更新的用户信息
@param userId 需要更新的用户ID
@discussion 使用此方法,可以更新SDK缓存的用户信息。
但是处于性能和使用场景权衡,SDK不会在当前View立即自动刷新(会在切换到其他View的时候再刷新该用户的显示信息)。
如果您想立即刷新,您可以在会话列表或者聊天界面reload强制刷新。
*/
- (void)refreshUserInfoCache:(RCUserInfo *)userInfo
withUserId:(NSString *)userId;
/*!
更新SDK中的群组信息缓存
@param groupInfo 需要更新的群组信息
@param groupId 需要更新的群组ID
@discussion 使用此方法,可以更新SDK缓存的群组信息。
但是处于性能和使用场景权衡,SDK不会在当前View立即自动刷新(会在切换到其他View的时候再刷新该群组的显示信息)。
如果您想立即刷新,您可以在会话列表或者聊天界面reload强制刷新。
*/
- (void)refreshGroupInfoCache:(RCGroup *)groupInfo
withGroupId:(NSString *)groupId;
安卓端:
/**
* 设置用户信息的提供者,供 RongIM 调用获取用户名称和头像信息。
*
* @param userInfoProvider 用户信息提供者。
* @param isCacheUserInfo 设置是否由 IMKit 来缓存用户信息。<br>
* 如果 App 提供的 UserInfoProvider
* 每次都需要通过网络请求用户数据,而不是将用户数据缓存到本地内存,会影响用户信息的加载速度;<br>
* 此时最好将本参数设置为 true,由 IMKit 将用户信息缓存到本地内存中。
* @see UserInfoProvider
*/
RongIM.setUserInfoProvider(new RongIM.UserInfoProvider() {
@Override
public UserInfo getUserInfo(String userId) {
return findUserById(userId);//根据 userId 去你的用户系统里查询对应的用户信息返回给融云 SDK。
}
}, true);
// 开发者自己重写 findUserById 方法通过if-else获取用户信息即可实现.
以上就是第二种方法的设置,其实可以看出我们最好的方法就是使用第二种“设置用户信息提供者”来显示头像昵称。
简而言之,在iOS端设置融云头像和昵称显示的时候,步骤就是:
1-遵守协议
RCIMUserInfoDataSource,RCIMGroupInfoDataSource
2-设置代理
[[RCIM sharedRCIM] setUserInfoDataSource:self];
[[RCIM sharedRCIM] setGroupInfoDataSource:self];
3-实现代理方法(if-else判断是否是当前用户,进行对应的属性设置即可)
- (void)getUserInfoWithUserId:(NSString *)userId
completion:(void (^)(RCUserInfo *userInfo))completion;
- (void)getGroupInfoWithGroupId:(NSString *)groupId
completion:(void (^)(RCGroup *groupInfo))completion;
另外,最重要的一点就是不要将两种方法混在一起使用,这样会造成不必要的bug。
以上就是关于融云头像昵称设置的相关内容,希望可以对大家有所帮助
我是姣爷,我在简书,和你们一起,加油,
康撒哈米哒~~~
网友评论
还有这个refreshuserinfocache方法在哪个类里 我该怎么调用 我想在更改个人信息成功的时候调用这个刷新融云数据库的数据是不是调用refreshuserinfocache这个方法?
- (void)getUserInfoWithUserId:(NSString *)userId completion:(void (^)(RCUserInfo *userInfo))completion 这个方法中有没有处理用户信息,另外就是如果是和安卓端调试,最好是两者使用统一的方式