OC即时聊天-对接融云填坑攻略
最近一段时间,开了一个新项目,涉及到即时聊天.对接的融云,也是踩了无数个坑.在这里总结一下,供大家参考.
如果你也遇到了问题.欢迎留言,自我感觉也是踩完大部分坑了.
一.注册融云 下载并接入SDK
这个其实没啥说的, https://www.rongcloud.cn/docs/ios.html 官方链接,可以帮你完成基本的接入及使用问题.
二.信息提供者
这是最坑的地方,也是融云核心所在. 涉及到的东西有点多,可能会说的有点乱.
先看官方说法:
融云认为,每一个设计良好且功能健全的 App 都应该能够在本地获取、缓存并在合适的时机更新 App 中的用户信息。所以,融云不维护和管理用户基本信息(用户ID、昵称、头像)的获取、缓存、变更和同步。
核心模式解答:
官方的意思就是说,我不保存头像和昵称这些信息. 我只有对话信息. app服务器(自己的接口)和融云都有聊天对象的id,用id来识别.完成整个数据的拼接组合.而这个过程的入口,就是信息提供者的几个方法.
我贴一下我的实现代码.和实现逻辑. 为了完成单聊和群聊.这几个代理都实现了.
1.在AppDelegate初始化融云,并创建信息提供者单例类,CTRongManager.
- (void)initRongClound:(UIApplication *)application{
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
//融云
[[RCIM sharedRCIM] initWithAppKey:key_rongyun];
//设置用户信息提供者为 [RCDataManager shareManager]
[RCIM sharedRCIM].userInfoDataSource = [CTRongManager shareManager];
//设置群组信息提供者为 [RCDataManager shareManager]
[RCIM sharedRCIM].groupInfoDataSource = [CTRongManager shareManager];
//群成员数据源
[RCIM sharedRCIM].groupMemberDataSource = [CTRongManager shareManager];
//群成员名片
[RCIM sharedRCIM].groupUserInfoDataSource = [CTRongManager shareManager];;
//头像设置
[RCIM sharedRCIM].portraitImageViewCornerRadius = 15;
//开启消息@功能(只支持群聊和讨论组, App需要实现群成员数据源groupMemberDataSource)
[RCIM sharedRCIM].enableMessageMentioned = YES;
//开启消息撤回功能
[RCIM sharedRCIM].enableMessageRecall = YES;
//开启用户信息和群组信息的持久化
[RCIM sharedRCIM].enablePersistentUserInfoCache = YES;
//SDK中全局的导航按钮字体颜色
[RCIM sharedRCIM].globalNavigationBarTintColor = [UIColor blackColor];
//关闭声音
[RCIM sharedRCIM].disableMessageAlertSound = YES;
[RCIM sharedRCIM].receiveMessageDelegate = self;
/**
* 推送处理1
*/
if ([application
respondsToSelector:@selector(registerUserNotificationSettings:)]) {
//注册推送, 用于iOS8以及iOS8之后的系统
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
[application registerUserNotificationSettings:settings];
} else {
//注册推送,用于iOS8之前的系统
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didReceiveMessageNotification:)
name:RCKitDispatchMessageNotification
object:nil];
}
我们开启了很多功能 用不到的话,可以不开启.
下面是核心代码,CTRongManager单例类.
CTRongManager.h
#import <Foundation/Foundation.h>
#import <RongIMKit/RongIMKit.h>
@interface CTRongManager : NSObject <RCIMUserInfoDataSource,RCIMGroupInfoDataSource,RCIMGroupUserInfoDataSource,RCIMGroupMemberDataSource>
/**
* CTRongManager单例对象
*
* @return CTRongManager单例
*/
+(CTRongManager *) shareManager;
/**
* 登录融云服务器(connect,用token去连接)
*
* @param token token令牌
*/
-(void)loginRongCloud;
/**
* 刷新tabbar的角标
*/
-(void) refreshBadgeValue;
//获取个人信息
- (void)getUserInfoWithUserId:(NSString*)userId completion:(void (^)(RCUserInfo*))completion;
//获取获取群信息信息
- (void)getGroupInfoWithGroupId:(NSString *)groupId
completion:(void (^)(RCGroup *groupInfo))completion;
//获取群组内的用户信息。
- (void)getUserInfoWithUserId:(NSString *)userId
inGroup:(NSString *)groupId
completion:(void (^)(RCUserInfo *userInfo))completion;
@end
CTRongManager.m (都有注释)
#import "CTRongManager.h"
#import "CTRongCloudHandle.h"
#import "CTRongGroupModel.h"
@implementation CTRongManager
- (instancetype)init{
if (self = [super init]) {
[RCIM sharedRCIM].userInfoDataSource = self;
[RCIM sharedRCIM].groupInfoDataSource = self;
[RCIM sharedRCIM].groupUserInfoDataSource = self;
[RCIM sharedRCIM].groupMemberDataSource = self;
}
return self;
}
+ (CTRongManager *)shareManager{
static CTRongManager* manager = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
manager = [[[self class] alloc] init];
});
return manager;
}
//获取rongcloudToken
-(void)loginRongCloud{
[CTRongCloudHandle getRongCloudWithsuccess:^(NSDictionary * obj) {
[self connectRongClound:obj[@"rongcloudToken"]];
} failed:^(id obj) {
[SVProgressHUD showErrorWithStatus:obj];
}];
}
//链接融云
-(void)connectRongClound:(NSString *)rongcloudToken{
[SVProgressHUD show];
[[RCIM sharedRCIM] connectWithToken:rongcloudToken success:^(NSString *userId) {
[SVProgressHUD dismiss];
NSLog(@"登陆成功。当前登录的用户ID:%@", userId);
//设置用户自己,这个很重要,不写的话,在对话页面可能看不到自己的头像信息.
RCUserInfo * user = [[RCUserInfo alloc]initWithUserId:[CTUserInfor shareUser].userId name:[CTUserInfor shareUser].nickName portrait:[CTUserInfor shareUser].avatarUrl];
[[RCIM sharedRCIM] setCurrentUserInfo:user];
[[CTRongManager shareManager] refreshBadgeValue];
//下面的两个请求算是优化,在开始的时候,请求数据,存数据库.可以做到使用的时候,直接取.
//获取好友关系
[CTRongCloudHandle getContactRelationShipWithsuccess:^(id obj) {
NSLog(@"好友信息");
} failed:^(id obj) {
}];
//获取群组关系
[CTRongCloudHandle getGroupRelationShipWithsuccess:^(id obj) {
NSLog(@"群组信息");
//同步群成员信息
for (CTRongGroupModel *model in obj) {
[CTRongCloudHandle getGroupMembersWithgroupId:model.groupId success:^(NSArray * obj) {
} failed:^(id obj) {
}];
}
} failed:^(id obj) {
}];
} error:^(RCConnectErrorCode status) {
NSLog(@"登陆的错误码为:%ld", (long)status);
[SVProgressHUD dismiss];
UIAlertController *alertText = [UIAlertController alertControllerWithTitle:@"提示" message:@"聊天系统连接失败,请点击重连" preferredStyle:UIAlertControllerStyleAlert];
[alertText addAction:[UIAlertAction actionWithTitle:@"算了,不连了" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
}]];
[alertText addAction:[UIAlertAction actionWithTitle:@"重新连接" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
//重新连接
[self connectRongClound:rongcloudToken];
}]];
[kKeyWindow.rootViewController presentViewController:alertText animated:YES completion:nil];
} tokenIncorrect:^{
[SVProgressHUD dismiss];
//token过期或者不正确。
//如果设置了token有效期并且token过期,请重新请求您的服务器获取新的token
//如果没有设置token有效期却提示token错误,请检查您客户端和服务器的appkey是否匹配,还有检查您获取token的流程。
NSLog(@"token错误");
UIAlertController *alertText = [UIAlertController alertControllerWithTitle:@"提示" message:@"聊天系统连接失败,请点击重连" preferredStyle:UIAlertControllerStyleAlert];
[alertText addAction:[UIAlertAction actionWithTitle:@"算了,不连了" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
}]];
[alertText addAction:[UIAlertAction actionWithTitle:@"重新连接" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
//连token一起重新请求,连接
[self loginRongCloud];
}]];
[kKeyWindow.rootViewController presentViewController:alertText animated:YES completion:nil];
}];
}
#pragma mark
#pragma mark - RCIMUserInfoDataSource
- (void)getUserInfoWithUserId:(NSString*)userId completion:(void (^)(RCUserInfo*))completion
{
if ([userId isEqualToString:[CTUserInfor shareUser].userId]) {
RCUserInfo * user = [[RCUserInfo alloc]initWithUserId:[CTUserInfor shareUser].userId name:[CTUserInfor shareUser].nickName portrait:[CTUserInfor shareUser].avatarUrl];
completion(user);
}else{
CTRongUserModel * model = [[CTDataBaseManager shareInstance] getUserByUserId:userId];
if (model.friendUserId) {
RCUserInfo * user = [[RCUserInfo alloc]initWithUserId:model.friendUserId name:model.friendNickName portrait:model.avatarUrl];
completion(user);
}else{
//获取 任何人都行
[CTRongCloudHandle getUserinforWithUserId:userId success:^(CTRongUserModel * userModel) {
RCUserInfo * user = [[RCUserInfo alloc]initWithUserId:userModel.friendUserId name:userModel.friendNickName portrait:userModel.avatarUrl];
completion(user);
} failed:^(id obj) {
}];
}
}
}
#pragma mark - RCIMGroupInfoDataSource
- (void)getGroupInfoWithGroupId:(NSString *)groupId
completion:(void (^)(RCGroup *groupInfo))completion{
CTRongGroupModel * model = [[CTDataBaseManager shareInstance] getGroupByGroupId:groupId];
if (model.groupId) {
RCGroup * group = [[RCGroup alloc]initWithGroupId:model.groupId groupName:model.groupName portraitUri:model.avatarUrl];
completion(group);
}else{
[CTRongCloudHandle getRelationshipWithfriendGroupIds:groupId success:^(NSArray * list) {
CTRongGroupModel * groupModel = list[0];
RCGroup * group = [[RCGroup alloc]initWithGroupId:groupModel.groupId groupName:groupModel.groupName portraitUri:groupModel.avatarUrl];
completion(group);
} failed:^(id obj) {
}];
}
}
#pragma mark - RCIMGroupUserInfoDataSource
/**
* 获取群组内的用户信息。
* 如果群组内没有设置用户信息,请注意:1,不要调用别的接口返回全局用户信息,直接回调给我们nil就行,SDK会自己巧用用户信息提供者;2一定要调用completion(nil),这样SDK才能继续往下操作。
*
* @param groupId 群组ID.
* @param completion 获取完成调用的BLOCK.
*/
- (void)getUserInfoWithUserId:(NSString *)userId
inGroup:(NSString *)groupId
completion:(void (^)(RCUserInfo *userInfo))completion {
//在这里查询该group内的群名片信息,如果能查到,调用completion返回。如果查询不到也一定要调用completion(nil)
//数据库取
NSArray * members = [[CTDataBaseManager shareInstance] getGroupMember:groupId];
if (members.count > 0) {
for (RCUserInfo * user in members) {
if ([user.userId isEqualToString:userId]) {
completion(user);
}
}
}else{
//没取到 请求 获取 任何人都行
[CTRongCloudHandle getUserinforWithUserId:userId success:^(CTRongUserModel * userModel) {
RCUserInfo * user = [[RCUserInfo alloc]initWithUserId:userModel.friendUserId name:userModel.friendNickName portrait:userModel.avatarUrl];
completion(user);
} failed:^(id obj) {
completion(nil);
}];
}
}
- (void)getAllMembersOfGroup:(NSString *)groupId result:(void (^)(NSArray<NSString *> *userIdList))resultBlock{
NSArray * members = [[CTDataBaseManager shareInstance] getGroupMember:groupId];
if (members.count > 0) {
NSMutableArray *ret = [[NSMutableArray alloc] init];
for (RCUserInfo *user in members) {
[ret addObject:user.userId];
}
resultBlock(ret);
}else{
[CTRongCloudHandle getGroupMembersWithgroupId:groupId success:^(NSArray * obj) {
NSMutableArray *ret = [[NSMutableArray alloc] init];
for (RCUserInfo *user in obj) {
[ret addObject:user.userId];
}
resultBlock(ret);
} failed:^(id obj) {
}];
}
}
//刷新角标
-(void)refreshBadgeValue{
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger unreadMsgCount = (NSInteger)[[RCIMClient sharedRCIMClient] getUnreadCount:@[@(ConversationType_PRIVATE),@(ConversationType_GROUP)]];
UINavigationController *chatNav = ((CTTabBarController*)kKeyWindow.rootViewController).viewControllers[1];
if (unreadMsgCount == 0) {
chatNav.tabBarItem.badgeValue = nil;
}else{
if (unreadMsgCount>=100) {
chatNav.tabBarItem.badgeValue = @"99+";
}else{
chatNav.tabBarItem.badgeValue = [NSString stringWithFormat:@"%li",(long)unreadMsgCount];
}
}
});
}
@end
上面就是各种信息提供者的各种实现,有几点需要注意
1.实现代理要遵守代理.别忘了
[RCIM sharedRCIM].userInfoDataSource = self;
[RCIM sharedRCIM].groupInfoDataSource = self;
[RCIM sharedRCIM].groupUserInfoDataSource = self;
[RCIM sharedRCIM].groupMemberDataSource = self;
2.实现的代理就是信息提供者.实现的思路是:首先去数据库取(因为链接融云之后 我们进行了数据请求,获取到了部分用户数据并存入了数据库,数据库创建下面会提到),取不到的话就请求接口(这里就需要一个可以获取任何人信息的接口,用来补充数据.)
三.数据库的创建
fmdb的使用,主要存储用户和群组信息
CTDataBaseManager.h
#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h>
#import <RongIMKit/RongIMKit.h>
#import "CTRongUserModel.h"
#import "CTRongGroupModel.h"
@interface CTDataBaseManager : NSObject
+ (CTDataBaseManager *)shareInstance;
- (void)closeDBForDisconnect;
//存储用户信息
- (void)insertUserToDB:(CTRongUserModel *)user;
- (void)insertUserListToDB:(NSMutableArray *)userList complete:(void (^)(BOOL))result;
//从表中获取用户信息
- (CTRongUserModel *)getUserByUserId:(NSString *)userId;
//存储群组信息
- (void)insertGroupToDB:(CTRongGroupModel *)group;
//会崩溃(已弃用)
- (void)insertGroupsToDB:(NSMutableArray *)groupList complete:(void (^)(BOOL))result;
//从表中获取群组信息
- (CTRongGroupModel *)getGroupByGroupId:(NSString *)groupId;
//删除表中的群组信息
- (void)deleteGroupToDB:(NSString *)groupId;
//清空表中的所有的群组信息
- (BOOL)clearGroupfromDB;
//清空群组缓存数据
- (void)clearGroupsData;
//存储群组成员信息
- (void)insertGroupMemberToDB:(NSMutableArray *)groupMemberList
groupId:(NSString *)groupId
complete:(void (^)(BOOL))result;
//从表中获取群组成员信息
- (NSMutableArray *)getGroupMember:(NSString *)groupId;
/*
* 获取所有用户信息
*/
- (NSArray *)getAllUserInfo:(void (^)(void))completion;
/*
* 获取所有群组信息
*/
- (NSArray *)getAllGroupInfo:(void (^)(void))completion;
@end
CTDataBaseManager.m
#import "CTDataBaseManager.h"
#import "FMDatabase.h"
#import "FMDatabaseQueue.h"
@interface CTDataBaseManager ()
@property(nonatomic, strong) FMDatabaseQueue *dbQueue;
@end
@implementation CTDataBaseManager
static NSString *const userTableName = @"USERTABLE";
static NSString *const groupTableName = @"GROUPTABLEV2";
static NSString *const groupMemberTableName = @"GROUPMEMBERTABLE";
+ (CTDataBaseManager *)shareInstance {
static CTDataBaseManager *instance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
instance = [[[self class] alloc] init];
[instance dbQueue];
});
return instance;
}
- (FMDatabaseQueue *)dbQueue {
if ([RCIMClient sharedRCIMClient].currentUserInfo.userId == nil) {
return nil;
}
if (!_dbQueue) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *const roungCloud = @"RongCloud";
NSString *library = [[paths objectAtIndex:0] stringByAppendingPathComponent:roungCloud];
NSString *dbPath = [library
stringByAppendingPathComponent:[NSString
stringWithFormat:@"RongIMDemoDB%@",
[RCIMClient sharedRCIMClient].currentUserInfo.userId]];
_dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
if (_dbQueue) {
[self createUserTableIfNeed];
}
}
return _dbQueue;
}
//创建用户存储表
- (void)createUserTableIfNeed {
[self.dbQueue inDatabase:^(FMDatabase *db) {
if (![self isTableOK:userTableName withDB:db]) {
NSString *createTableSQL = @"CREATE TABLE USERTABLE (id integer PRIMARY "
@"KEY autoincrement, friendUserId text,friendNickName text, "
@"avatarUrl text)";
[db executeUpdate:createTableSQL];
NSString *createIndexSQL = @"CREATE unique INDEX idx_userid ON USERTABLE(friendUserId);";
[db executeUpdate:createIndexSQL];
}
if (![self isTableOK:groupTableName withDB:db]) {
NSString *createTableSQL = @"CREATE TABLE GROUPTABLEV2 (id integer PRIMARY KEY autoincrement, "
@"groupId text,groupName text, avatarUrl text,displayName text,roleType "
@"text ,notDisturb text ,groupBanState text,banState text, banDate "
@"text)";
[db executeUpdate:createTableSQL];
NSString *createIndexSQL = @"CREATE unique INDEX idx_groupid ON GROUPTABLEV2(groupId);";
[db executeUpdate:createIndexSQL];
}
if (![self isTableOK:groupMemberTableName withDB:db]) {
NSString *createTableSQL = @"CREATE TABLE GROUPMEMBERTABLE (id integer "
@"PRIMARY KEY autoincrement, groupid text, "
@"userid text,name text, portraitUri text)";
[db executeUpdate:createTableSQL];
NSString *createIndexSQL = @"CREATE unique INDEX idx_groupmemberId ON "
@"GROUPMEMBERTABLE(groupid,userid);";
[db executeUpdate:createIndexSQL];
}
}];
}
- (void)closeDBForDisconnect {
self.dbQueue = nil;
}
//存储用户信息(任何人)
- (void)insertUserToDB:(CTRongUserModel *)user {
NSString *insertSql = @"REPLACE INTO USERTABLE (friendUserId, friendNickName, avatarUrl) VALUES (?, ?, ?)";
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:insertSql, user.friendUserId, user.friendNickName, user.avatarUrl];
}];
}
//存储用户列表信息(任何人)
- (void)insertUserListToDB:(NSMutableArray *)userList complete:(void (^)(BOOL))result {
if (userList == nil || [userList count] < 1)
return;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
for (CTRongUserModel *user in userList) {
NSString *insertSql = @"REPLACE INTO USERTABLE (friendUserId, friendNickName, avatarUrl) VALUES (?, ?, ?)";
[db executeUpdate:insertSql, user.friendUserId, user.friendNickName, user.avatarUrl];
}
}];
result(YES);
});
}
//从表中获取用户信息
- (CTRongUserModel *)getUserByUserId:(NSString *)friendUserId {
__block CTRongUserModel *model = nil;
[self.dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM USERTABLE where friendUserId = ?", friendUserId];
while ([rs next]) {
model = [[CTRongUserModel alloc] init];
model.friendUserId = [rs stringForColumn:@"friendUserId"];
model.friendNickName = [rs stringForColumn:@"friendNickName"];
model.avatarUrl = [rs stringForColumn:@"avatarUrl"];
}
[rs close];
}];
return model;
}
//从表中获取所有用户信息
- (NSArray *)getAllUserInfo {
NSMutableArray *allUsers = [NSMutableArray new];
[self.dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM USERTABLE"];
while ([rs next]) {
CTRongUserModel *model;
model = [[CTRongUserModel alloc] init];
model.friendUserId = [rs stringForColumn:@"friendUserId"];
model.friendNickName = [rs stringForColumn:@"friendNickName"];
model.avatarUrl = [rs stringForColumn:@"avatarUrl"];
[allUsers addObject:model];
}
[rs close];
}];
return allUsers;
}
//存储群组信息
- (void)insertGroupToDB:(CTRongGroupModel *)group {
if (group == nil || [group.groupId length] < 1)
return;
NSString *insertSql = @"REPLACE INTO GROUPTABLEV2 (groupId, "
@"groupName,avatarUrl,displayName,roleType,notDisturb,"
@"groupBanState,banState,banDate) VALUES "
@"(?,?,?,?,?,?,?,?,?)";
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:insertSql, group.groupId, group.groupName, group.avatarUrl, group.displayName, group.roleType,
group.notDisturb, group.groupBanState, group.banState,
group.banDate];
}];
}
- (void)insertGroupsToDB:(NSMutableArray *)groupList complete:(void (^)(BOOL))result {
if (groupList == nil || [groupList count] < 1)
return;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
for (CTRongGroupModel *group in groupList) {
NSString *insertSql = @"REPLACE INTO GROUPTABLEV2 (groupId, "
@"groupName,avatarUrl,displayName,roleType,notDisturb,"
@"groupBanState,banState,banDate) VALUES "
@"(?,?,?,?,?,?,?,?,?)";
[db executeUpdate:insertSql, group.groupId, group.groupName, group.avatarUrl, group.displayName, group.roleType,
group.notDisturb, group.groupBanState, group.banState,
group.banDate];
}
}];
result(YES);
});
}
//从表中获取群组信息
- (CTRongGroupModel *)getGroupByGroupId:(NSString *)groupId {
__block CTRongGroupModel *model = nil;
[self.dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM GROUPTABLEV2 where groupId = ?", groupId];
while ([rs next]) {
model = [[CTRongGroupModel alloc] init];
model.groupId = [rs stringForColumn:@"groupId"];
model.groupName = [rs stringForColumn:@"groupName"];
model.avatarUrl = [rs stringForColumn:@"avatarUrl"];
model.displayName = [rs stringForColumn:@"displayName"];
model.roleType = [rs stringForColumn:@"roleType"];
model.notDisturb = [rs stringForColumn:@"notDisturb"];
model.groupBanState = [rs stringForColumn:@"groupBanState"];
model.banState = [rs stringForColumn:@"banState"];
model.banDate = [rs stringForColumn:@"banDate"];
}
[rs close];
}];
return model;
}
//删除表中的群组信息
- (void)deleteGroupToDB:(NSString *)groupId {
if ([groupId length] < 1)
return;
NSString *deleteSql =
[NSString stringWithFormat:@"delete from %@ where %@ = '%@'", @"GROUPTABLEV2", @"groupid", groupId];
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:deleteSql];
}];
}
//清空表中的所有的群组信息
- (BOOL)clearGroupfromDB {
__block BOOL result = NO;
NSString *clearSql = [NSString stringWithFormat:@"DELETE FROM GROUPTABLEV2"];
[self.dbQueue inDatabase:^(FMDatabase *db) {
result = [db executeUpdate:clearSql];
}];
return result;
}
//从表中获取所有群组信息
- (NSMutableArray *)getAllGroup {
NSMutableArray *allGroups = [NSMutableArray new];
[self.dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM GROUPTABLEV2"];
while ([rs next]) {
CTRongGroupModel *model;
model = [[CTRongGroupModel alloc] init];
model.groupId = [rs stringForColumn:@"groupId"];
model.groupName = [rs stringForColumn:@"name"];
model.avatarUrl = [rs stringForColumn:@"avatarUrl"];
model.displayName = [rs stringForColumn:@"displayName"];
model.roleType = [rs stringForColumn:@"roleType"];
model.notDisturb = [rs stringForColumn:@"notDisturb"];
model.groupBanState = [rs stringForColumn:@"groupBanState"];
model.banState = [rs stringForColumn:@"banState"];
model.banDate = [rs stringForColumn:@"banDate"];
[allGroups addObject:model];
}
[rs close];
}];
return allGroups;
}
//存储群组成员信息
- (void)insertGroupMemberToDB:(NSMutableArray *)groupMemberList
groupId:(NSString *)groupId
complete:(void (^)(BOOL))result {
if (groupMemberList == nil || [groupMemberList count] < 1)
return;
NSString *deleteSql =
[NSString stringWithFormat:@"delete from %@ where %@ = '%@'", @"GROUPMEMBERTABLE", @"groupid", groupId];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:deleteSql];
for (RCUserInfo *user in groupMemberList) {
NSString *insertSql = @"REPLACE INTO GROUPMEMBERTABLE (groupid, userId, "
@"name, portraitUri) VALUES (?, ?, ?, ?)";
[db executeUpdate:insertSql, groupId, user.userId, user.name, user.portraitUri];
}
}];
result(YES);
});
}
//从表中获取群组成员信息
- (NSMutableArray *)getGroupMember:(NSString *)groupId {
NSMutableArray *allUsers = [NSMutableArray new];
[self.dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT * FROM GROUPMEMBERTABLE where groupid=? order by id", groupId];
while ([rs next]) {
// RCUserInfo *model;
RCUserInfo *model;
model = [[RCUserInfo alloc] init];
model.userId = [rs stringForColumn:@"userId"];
model.name = [rs stringForColumn:@"name"];
model.portraitUri = [rs stringForColumn:@"portraitUri"];
[allUsers addObject:model];
}
[rs close];
}];
return allUsers;
}
//清空群组缓存数据
- (void)clearGroupsData {
NSString *deleteSql = @"DELETE FROM GROUPTABLEV2";
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:deleteSql];
}];
}
- (NSArray *)getAllUserInfo:(void (^)(void))completion {
return [[CTDataBaseManager shareInstance] getAllUserInfo];
}
- (NSArray *)getAllGroupInfo:(void (^)(void))completion {
return [[CTDataBaseManager shareInstance] getAllGroup];
}
- (BOOL)isTableOK:(NSString *)tableName withDB:(FMDatabase *)db {
BOOL isOK = NO;
FMResultSet *rs = [db executeQuery:@"select count(*) as 'count' from sqlite_master where "
@"type ='table' and name = ?",
tableName];
while ([rs next]) {
NSInteger count = [rs intForColumn:@"count"];
if (0 == count) {
isOK = NO;
} else {
isOK = YES;
}
}
[rs close];
return isOK;
}
- (BOOL)isColumnExist:(NSString *)columnName inTable:(NSString *)tableName withDB:(FMDatabase *)db {
BOOL isExist = NO;
NSString *columnQurerySql = [NSString stringWithFormat:@"SELECT %@ from %@", columnName, tableName];
FMResultSet *rs = [db executeQuery:columnQurerySql];
if ([rs next]) {
isExist = YES;
} else {
isExist = NO;
}
[rs close];
return isExist;
}
@end
这就是用户信息的存储,这是必要的.不可能所有的信息每次都请求接口.
基本上都这么写,没啥好说的.
四:通知推送.
首先你要知道本地通知和远程推送.在程序进入后台一段时间后,app被杀死. 才进入远程推送.推送的开启和关闭,我这边最后的结果是这样做的.
首先进入app,默认关闭推送声音,
//关闭声音
[RCIM sharedRCIM].disableMessageAlertSound = YES;
然后在设置里面给一个开关,这个开关没有那么详细.就是开启或者关闭推送和通知.只要你关闭了,无论是推送还是通知统统收不到.
-(void)totalSwitchClick:(UISwitch *)swiftch{
[SVProgressHUD show];
if (swiftch.on) {
[[RCIMClient sharedRCIMClient] setNotificationQuietHours:@"00:00:00"
spanMins:1439
success:^{
[SVProgressHUD dismiss];
[CTUserInfor shareUser].isOpenMessage = @"1";
}
error:^(RCErrorCode status) {
[SVProgressHUD dismiss];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"设置失败"
delegate:nil
cancelButtonTitle:@"取消"
otherButtonTitles:nil, nil];
[alert show];
swiftch.on = NO;
});
}];
} else {
[[RCIMClient sharedRCIMClient] removeNotificationQuietHours:^{
[SVProgressHUD dismiss];
[CTUserInfor shareUser].isOpenMessage = @"0";
}
error:^(RCErrorCode status) {
[SVProgressHUD dismiss];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"取消失败"
delegate:nil
cancelButtonTitle:@"取消"
otherButtonTitles:nil, nil];
[alert show];
swiftch.on = YES;
});
}];
}
}
剩下的就是一些ui的自定制什么的了.
整体来说,融云还是蛮难接的.