环信的EaseUI里,实现了微信的消息,通讯录两大模块的UI,功能,可说老少兼宜,对比下两者的ui:
基本上集成来EaseUI就相当于集成了微信通讯功能,好友功能。具体集成,详见环信官网
Q1.环信好友关系维护
环信维护了一个好友体系,在时间比较紧促的情况下,我们可以使用环信的好友体系,但是,在时间比较充足的情况下,还是建议由我们自己服务器去维护好友体系,因为环信维护的好友体系,仅在需要控制消息发送权限时才启动,而且环信保存的只是环信id,没有头像,昵称这些信息
两者对比:
- 环信好友体系,需要使用环信的id去访问自己的服务器,以便获取好友的基本信息(基本的头像,昵称….)
- 自己服务器好友体系,获取好友的时候,直接访问服务器接口,不用访问环信服务器,比较方便
Q2.头像昵称
环信服务器保存的只是我们的环信id,不支持保存其它信息,我们也不会希望它保存着我们的其它信息,在环信的demo里面,其实已经使用了Parse来保存用户的头像昵称,主要代码在UserProfileManager
这个类里面:
其中是以环信的id(username
)作为key,将头像昵称保存到Parse,使用的时候从Parse读取,保存在本地的一个NSMutableDictionary
中,需要展示的时候,通过环信id(username
)来获取对应的信息,具体可以看下UserProfileManager.m
的实现
不过我们还是使用我们自己服务器来保存这些信息,防止数据错乱,如果使用Parse,在更新自己服务器头像昵称的同时还需要更新Parse上的信息,而且Parse也快到期了,比较麻烦,所以我们可以参照UserProfileManager
,自己实现好友头像昵称的本地缓存,在环信的论坛已经有人发表了相关的文章:iOS开发小记:关于环信Demo3.0的使用总结以及昵称和头像问题的研究与解决,以下是在这文章的基础上,自己增加了两个更新本地头像昵称的方法,目前这些信息是存储在NSUserDefaults
中
#define dUserDefaults_Dic_NickName @"dUserDefaults_Dic_NickName"
#define dUserDefaults_Dic_HeadImage @"dUserDefaults_Dic_HeadImage"
@interface CacheData()
@property (strong, nonatomic) NSMutableDictionary *NickNames;
@property (strong, nonatomic) NSMutableDictionary *HeadImages;
@property (nonatomic) BOOL LoadFromLocalDickDone;
@end
@implementation CacheData
static CacheData* _instance = nil;
+(instancetype) shareInstance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init] ;
}) ;
return _instance ;
}
- (instancetype)init
{
self = [super init];
if (self) {
_DownloadHasDone = NO;
_LoadFromLocalDickDone = NO;
NSMutableDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:dUserDefaults_Dic_NickName];
if (dic == nil || [dic count] == 0) {
_NickNames = [NSMutableDictionary dictionary];
_HeadImages= [NSMutableDictionary dictionary];
_LoadFromLocalDickDone = YES;
}
else
{
_LoadFromLocalDickDone = YES;
_NickNames = [NSMutableDictionary dictionaryWithDictionary:dic];
_HeadImages= [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] objectForKey:dUserDefaults_Dic_HeadImage]];
}
}
return self;
}
- (void)clearParse
{
[_NickNames removeAllObjects];
[_HeadImages removeAllObjects];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:_NickNames forKey:dUserDefaults_Dic_NickName];
[ud setObject:_HeadImages forKey:dUserDefaults_Dic_HeadImage];
[ud synchronize];
}
- (void)loadUserProfileInBackgroundCompletion:(void (^)())completion
{
_DownloadHasDone = NO;
GetUserFriendParam *param = [GetUserFriendParam new];
param.SNSID = userId;
[[[FriendCircle_GetUserFriend_BLController alloc] initWithParam:param] startWithCompletionBlockWithSuccess:^(ZQBLBaseController *blController) {
_LoadFromLocalDickDone = NO;
if ([blController.responseObject isKindOfClass:[NSArray class]]) {
NSArray *arr = (NSArray *)blController.responseObject;
for (GetUserFriendModel *model in arr) {
[_NickNames setObject:model.NickName forKey:[NSString stringWithFormat:@"%@",model.userId]];
[_HeadImages setObject:model.FaceImg forKey:[NSString stringWithFormat:@"%@",model.userId]];
}
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:_NickNames forKey:dUserDefaults_Dic_NickName];
[ud setObject:_HeadImages forKey:dUserDefaults_Dic_HeadImage];
[ud synchronize];
}
_LoadFromLocalDickDone = YES;
_DownloadHasDone = YES;
if (completion) {
completion();
}
} failure:^(ZQBLBaseController *blController) {
_DownloadHasDone = NO;
if (completion) {
completion();
}
}];
}
- (void)updateNicknameWithUsername:(NSString *)username nickname:(NSString *)nickname
{
[_NickNames setObject:nickname forKey:[NSString stringWithFormat:@"%@",username]];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:_NickNames forKey:dUserDefaults_Dic_NickName];
[ud synchronize];
}
- (void)updateHeadImageWithUsername:(NSString *)username headimage:(NSString *)headimage
{
[_HeadImages setObject:headimage forKey:[NSString stringWithFormat:@"%@",username]];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:_HeadImages forKey:dUserDefaults_Dic_HeadImage];
[ud synchronize];
}
- (NSString*)getNicknameByUserName:(NSString*)username
{
if(_DownloadHasDone == YES)
{
NSString *string = [_NickNames objectForKey:username];
if (string == nil || [string length] == 0) {
return username;
}
return string;
}
else if(_LoadFromLocalDickDone == YES)
{
NSMutableDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:dUserDefaults_Dic_NickName];
NSString *string = [dic objectForKey:username];
if (string == nil || [string length] == 0) {
return username;
}
return string;
}
return username;
}
- (NSString*)getHeadImageUrlByUserName:(NSString*)username
{
if(_DownloadHasDone == YES)
{
NSString *string = [_HeadImages objectForKey:username];
if (string == nil || [string length] == 0) {
return @"";
}
return string;
}
else if(_LoadFromLocalDickDone == YES)
{
NSMutableDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:dUserDefaults_Dic_HeadImage];
NSString *string = [dic objectForKey:username];
if (string == nil || [string length] == 0) {
return @"";
}
return string;
}
return @"";
}
@end
在app刚运行的时候,调用loadUserProfileInBackgroundCompletion
加载并缓存好友头像的url
以及好友昵称
,然后将环信demo中的UserProfileEntity
的getUserProfileByUsername
换成CacheData
的getNicknameByUserName
,如下面的聊天会话列表:
我们当前的项目,群聊都是使用默认头像,所以当聊天会话类型为单聊(EMConversationTypeChat
)时才去加载头像昵称。
替换了所有的UserProfileEntity
为我们自己的CacheData
,基本可以在单聊会话中准确的显示昵称和头像,但是,当我们查看某个人的个人资料时,最好将获取到的最新资料对本地缓存进行更新,以保证数据统一,调用updateHeadImageWithUsername
和updateNicknameWithUsername
即可更新本地缓存
下面看看关于在群聊聊天界面,我们如何展示昵称和头像:
是通过扩展消息去获取的,但是这有一个缺点,就是当对方更改了昵称或者头像的时候,之前的聊天记录的头像或者昵称还是旧的,并不会改变,由于项目比较赶,只能跟随着安卓端通过扩展消息去获取了,这个待到后面有时间必须优化
Q3.自动加入公开群后,提示XXX邀请你加入群组
//SDK自动同意了用户A的加B入群邀请后,用户B接收到该回调
- (void)didJoinedGroup:(EMGroup *)aGroup
inviter:(NSString *)aInviter
message:(NSString *)aMessage
{
//1
[self convertToNicknameWithUsrname:[NSString stringWithFormat:@"%@",aInviter] finish:^(NSString *nickname,NSString *imgUrl) {
//发送的消息体
NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:[NSString stringWithFormat:@"%@ 邀请你加入群组: %@",nickname,aGroup.subject]];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:willSendText];
//发送人
NSString *from = aInviter;//[[EMClient sharedClient] currentUsername];
//头像昵称
NSMutableDictionary *ext = [[NSMutableDictionary alloc] init];
[ext setValue:nickname forKey:@"group_nick_name"];
[ext setValue:imgUrl forKey:@"avatar"];
EMMessage *message = [[EMMessage alloc] initWithConversationID:aGroup.groupId from:from to:aGroup.groupId body:body ext:ext];
message.chatType = EMChatTypeGroupChat;
message.direction = EMMessageDirectionReceive;
EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aGroup.groupId type:EMConversationTypeGroupChat createIfNotExist:YES];
[conversation insertMessage:message];
[[ChatDemoHelper shareHelper].conversationListVC tableViewDidTriggerHeaderRefresh];
}];
}
convertToNicknameWithUsrname
是通过环信id去获取用户的昵称
Q4.使用po查看一些变量时use of undeclared identifier ‘XX’
How to debug member variable (ie., Array, Dictionary) in LLDB?