请前往 融云官方网站 注册开发者帐号。注册时,您需要提供真实的邮箱和手机号,以方便我们向您发送重要通知并在紧急时刻能够联系到您。如果您没有提供正确可用的邮箱和手机号,我们随时可能关闭您的应用。
您可以到 融云官方网站 下载融云 SDK。
SDK 下载包中分为如下两部分:
好的,下载应该已经开始了,您可以在下载过程中继续向下阅读。
首先,让我们先创建您的第一个应用吧!
您要进行应用开发之前,需要先在融云开发者平台创建应用。如果您已经注册了融云开发者帐号,请前往 融云开发者平台 创建应用;如果您还没有注册融云开发者帐号,请前往 融云官方网站 首先注册开发者帐号,注册后创建应用。
您创建完应用后,最需要了解的就是 App Key / Secret,它们是融云 SDK 连接服务器所必须的标识,每一个 App 对应一套 App Key / Secret。针对开发者的生产环境和开发环境,我们提供两套 App Key / Secret,您在应用最终上线前,使用开发环境即可,两套环境的功能完全一致。
创建 Demo 项目时,为了方便演示,请选择创建一个 Empty Application
。
CocoaPods 是流行的 Cocoa 项目依赖管理工具,我们推荐您优先使用 CocoaPods 来安装 SDK,这样可以极大的简化安装过程。下面介绍具体步骤:
在您的项目根目录创建一个 Podfile 文件,添加如下内容来引用 IMKit 界面组件库:
pod 'RongCloudIMKit'
如果您需要引用 IMLib 通讯能力库,可以添加:
pod 'RongCloudIMLib'
然后,执行命令 pod install
安装 融云 SDK。
您可以参考 《CocoaPods 安装和使用教程》 这篇文章来学习如何使用 CocoaPods。
此处特别感谢求攻略的 Zhuohui Yu 帮助创建和维护融云的 CocoaPods 项目。
将官网下载的 Rong_Cloud_iOS_SDK_vx_x_x.zip 包解压到任意目录。打开 imkit
目录,将 Headers
目录头文件、iOS_IMKit.a
文件和 RongCloud.bundle
文件加入到工程中。
工程中需要依赖的库如下(根据使用的功能不同,某些库并不是所有情况下都需要):
请使用您之前从融云开发者平台注册得到的 App Key,传入 initWithAppKey:deviceToken:
方法,初始化 SDK。deviceToken
是用于 Apple Push Notification Service 的设备唯一标识,获取方法请参阅苹果官方的 Local and Push Notification Programming Guide
在整个应用程序全局,只需要调用一次 initWithAppKey:deviceToken:
方法。这里,我们选择在 App 初始化时,来调用 initWithAppKey:deviceToken:
方法。当获取到 Push 通知权限时,使用 setDeviceToken
方法设置 deviceToken
。
initWithAppKey:deviceToken:
方法中的
deviceToken
参数已经被废弃,目前传入
nil
即可,后续版本中会去掉此参数。
AppDelegate.m 文件如下:
#import "AppDelegate.h"
// 引用 IMKit 头文件。
#import "RCIM.h"
// 引用 ViewController 头文件。
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
// 初始化 SDK,传入 App Key,deviceToken 暂时为空,等待获取权限。
[RCIM initWithAppKey:@"e7x8xycsx6flq" deviceToken:nil];
#ifdef __IPHONE_8_0
// 在 iOS 8 下注册苹果推送,申请推送权限。
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
|UIUserNotificationTypeSound
|UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
// 注册苹果推送,申请推送权限。
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
#endif
// 初始化 ViewController。
ViewController *viewController = [[ViewController alloc]initWithNibName:nil bundle:nil];
// 初始化 UINavigationController。
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:viewController];
// 设置背景颜色为黑色。
[nav.navigationBar setBackgroundColor:[UIColor blackColor]];
// 初始化 rootViewController。
self.window.rootViewController = nav;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
// Register to receive notifications.
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
// Handle the actions.
if ([identifier isEqualToString:@"declineAction"]){
}
else if ([identifier isEqualToString:@"answerAction"]){
}
}
#endif
// 获取苹果推送权限成功。
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 设置 deviceToken。
[[RCIM sharedRCIM] setDeviceToken:deviceToken];
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
e7x8xycsx6flq
仅为示例,直接拷贝执行将返回错误,请注意替换为您自己的 App Key 值。
Token 也叫用户令牌,是 SDK 端用来连接融云服务器的凭证,每个用户连接服务器都需要一个 Token。每次初始化连接服务器(请看下节)时,都需要向服务器提交 Token。
要想获取用户 Token,流程如下:首先需要您的 App 查询您的应用程序服务器,然后您的应用程序服务器再访问融云服务器获取,最后返回给 App,App 用返回的 Token 连接服务器登录。详细描述请参考 Server 开发指南 中的身份认证服务小节。
将您在上一节请求身份认证服务器时获取的 Token 传入 connectWithToken
方法,开始连接服务器。在整个应用程序全局,只需要调用一次 connectWithToken
方法,SDK 会负责自动重连。
您可以用在上一节介绍的 API 调试工具生成一个 Token,这里我们假设您生成 Token 时使用的参数如下:
用户 Id:
userId = "1"
用户在融云系统中唯一的身份 Id,可为任意数字或字符串,但必须保证全局唯一。
用户名称:
name = "韩梅梅"
用户的显示名称,用来在 Push 推送时,或者客户端没有提供用户信息时,显示用户的名称。
用户头像图片:
portraitUri = "http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png"
这里为了测试,您可以随意提供一个地址,如果此图片不存在,IMKit 会显示默认的头像。
假设返回的 Token 是 mKmyKqTSf7aNDinwAFMnz7NXKILeV3X0+CCRBOxmtOApmvQjMathViWrePIfq0GuTu9jELQqsckv4AhfjCAKgQ==。
以下代码展示了如何连接到融云服务器,完整代码请看下节。
// 连接融云服务器。
[RCIM connectWithToken:@"mKmyKqTSf7aNDinwAFMnz7NXKILeV3X0+CCRBOxmtOApmvQjMathViWrePIfq0GuTu9jELQqsckv4AhfjCAKgQ==" completion:^(NSString *userId) {
// 此处处理连接成功。
NSLog(@"Login successfully with userId: %@.", userId);
} error:^(RCConnectErrorCode status) {
// 此处处理连接错误。
NSLog(@"Login failed.");
}];
mKmyKqTSf7aNDinwAFMnz7NXKILeV3X0+CCRBOxmtOApmvQjMathViWrePIfq0GuTu9jELQqsckv4AhfjCAKgQ==
仅为示例,直接拷贝执行将返回错误,请注意替换为您自己的 Token 值。
单聊是最基本的聊天界面,在您的 App 中,您可以通过直接点击用户头像或者点击一个启动聊天按钮,直接调起单聊界面。
下面的代码,我们提供一个完整的案例来演示如何启动一个自己与自己单聊的例子(仅为演示,实际业务中不存在自己和自己聊天的场景)。在这个例子中,通过点击一个按钮来启动单聊界面。
ViewController.h 文件如下:
#import
@interface ViewController : UIViewController
// 定义一个按钮。
@property (nonatomic,strong) UIButton *button;
@end
ViewController.m 文件如下:
#import "ViewController.h"
// 引用 IMKit 头文件。
#import "RCIM.h"
// 引用 RCChatViewController 头文件。
#import "RCChatViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 创建一个按钮
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.button setFrame:CGRectMake(50, 100, 80, 40)];
[self.button setTitle:@"Start Chat" forState:UIControlStateNormal];
[self.button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button];
}
// 按钮点击事件。
-(IBAction)buttonClicked:(id)sender
{
// 连接融云服务器。
[RCIM connectWithToken:@"mKmyKqTSf7aNDinwAFMnz7NXKILeV3X0+CCRBOxmtOApmvQjMathViWrePIfq0GuTu9jELQqsckv4AhfjCAKgQ==" completion:^(NSString *userId) {
// 此处处理连接成功。
NSLog(@"Login successfully with userId: %@.", userId);
// 创建单聊视图控制器。
RCChatViewController *chatViewController = [[RCIM sharedRCIM]createPrivateChat:@"1" title:@"自问自答" completion:^(){
// 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
}];
// 把单聊视图控制器添加到导航栈。
[self.navigationController pushViewController:chatViewController animated:YES];
} error:^(RCConnectErrorCode status) {
// 此处处理连接错误。
NSLog(@"Login failed.");
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
原理同上,通过以下代码,您的 App 可以直接调起客服聊天界面。
其中,customerServiceId
的值,可以在 融云开发者平台 的客服模块中找到。位置为:xx应用 / 功能模块 / 客服模块 / 开发环境 / 查看详情。查看customerServiceId
之前,请您先开启客服功能。
// 创建客服聊天视图控制器。
RCChatViewController *chatViewController = [[RCIM sharedRCIM]createCustomerService:customerServiceId title:@"在线客服" completion:^(){
// 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
}];
// 把客服聊天视图控制器添加到导航栈。
[self.navigationController pushViewController:chatViewController animated:YES];
如果您需要会话列表界面,可以启动聊天会话列表,在聊天会话列表中,用户可以通过点击右上角的加号按钮创建聊天会话。当然,在有些场景下,您可能不需要会话列表,直接启动聊天会话窗口。
// 创建会话列表视图控制器。
RCChatListViewController *chatListViewController = [[RCIM sharedRCIM]createConversationList:^(){
// 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
}];
// 把会话列表视图控制器添加到导航栈。
[self.navigationController pushViewController:chatListViewController animated:YES];
setFriendsFetcherWithDelegate
,否则好友列表将不显示任何好友信息。关于好友信息提供者的信息,请参看下节文档。
群组业务的描述,请参见快速入门中的说明。
因群组信息与群成员信息是由 App 维护管理并提供的,所以,处理群组的业务逻辑就是处理数据同步的逻辑。主要逻辑如下:
开发文档链接:syncGroups:completion:error:
用于同步当前登录用户已经加入的群组信息,需要提交当前用户所有加入的群组信息(群组信息包含 groupId
:群唯一标识,groupName
:群名称)。 融云服务器会根据你提交的群信息与之前提交的群信息进行比对,根据差异结果进行加入或退出操作。提交此信息后该用户可以收到这些群的消息,且可以向这些群内发送数据。
开发文档链接:joinGroup:groupName:completion:error:
此方法可以在 App 运行过程中实现将当前登录用户加入群组。在方法响应成功后,该用户可以收到所加入的群组的消息,且可以向该群组发送数据。请在您的 App 中实现当前用户加入群组时,调用此方法。
开发文档链接:quitGroup:completion:error:
此方法可以在 App 运行过程中实现当前登录用户退出已加入的群组。在方法响应成功后,该用户将不会再收到该群组的消息,且不再可以向该群组发送数据。请在您的 App 中实现当前用户退出群组时,调用此方法。
聊天室业务的描述,请参见快速入门中的说明。
聊天室与群组最大的不同在于,聊天室的消息没有 Push 通知,也没有成员的概念。想参与聊天室聊天,接收聊天室消息,加入聊天室即可;不参与聊天室聊天,不接收消息,退出聊天室即可。IMKit 组件中已经内置了加入和退出讨论组的接口调用,您直接启动即可:
// 启动聊天室
RCChatViewController *temp = [[RCChatViewController alloc]init];
temp.currentTarget = @"19527";
temp.conversationType = ConversationType_CHATROOM;
temp.enableSettings = NO;
temp.currentTargetName = @"聊天室标题";
[self.navigationController pushViewController:temp animated:YES];
实现了以上功能以后,您就可以实现在 App 中的简单一对一聊天服务了,但是您还看不到用户昵称、头像等信息。所以,为了实现上述功能,您还需要在 App 真正发布前继续完善一些代码。
设计原理说明:
融云认为,每一个设计良好且功能健全的 App 都应该能够在本地获取、缓存并在合适的时机更新 App 中的用户信息。所以,融云不维护和管理用户的基本信息(用户 Id、昵称、头像)的获取、缓存、变更和同步。此外,App 提供用户信息也避免了由于缓存导致的用户信息更新不及时,App 中不同界面上的用户信息不统一(比如:一部分 App 从 App 服务器上获取并显示,一部分由融云服务器获取并显示),能够获得最佳的用户体验。
融云通过让开发者在 IMKit 中设置用户信息提供者
的方式来实现在聊天界面和会话列表页中实现通过 App 的数据源来显示用户昵称和头像。
设置用户信息提供者即通过调用 setUserInfoFetcherWithDelegate:isCacheUserInfo:
方法设置 RCIMUserInfoFetcherDelegagte
。用户信息提供者采用 Provider 模式,即您提供给融云的 IMKit 一个 RCIMUserInfoFetcherDelegagte
,当融云的 IMKit 需要使用用户信息的时候,调用您传入的getUserInfoWithUserId:
方法,向您获取用户信息。所以您在 getUserInfoWithUserId:
方法中,需要根据传入的 userId
参数,向我们返回对应的用户信息。
代码请参见下节 - 设置好友关系提供者,我们将一起展示。
[https://api.cn.rong.io/user/getToken.[format]](/server.html#_身份认证服务接口说明)
换取 Token 的方式将用户昵称和头像提供给我们,并且可以通过重新换取 Token 的方式刷新用户资料,但是我们非常不推荐这种方式。这种方式会造成客户端的性能问题和用户信息更新不及时。
为了客户隐私考虑,融云既不同步又不保存用户的好友关系。所以,当界面组件创建会话需要显示好友列表时,需要向 App 获取。App 需要设置一个好友关系提供者给 IMKit,以便 IMKit 读取好友关系。好友关系提供者 RCIMFriendsFetcherDelegate
的设计模式与用户信息提供者 RCIMUserInfoFetcherDelegagte
相同,可以参考用户信息提供者 RCIMUserInfoFetcherDelegagte
的说明。
在群组业务中,融云只是同步群组关系数据,并不保存群组的具体信息。所以,当界面组件创建会话需要显示群组信息时,需要向 App 获取。App 需要设置一个群组信息提供者给 IMKit,以便 IMKit 读取好友关系。群组信息提供者 RCIMGroupInfoFetcherDelegate
的设计模式与用户信息提供者 RCIMUserInfoFetcherDelegagte
相同,可以参考用户信息提供者 RCIMUserInfoFetcherDelegagte
的说明。
代码分成两部分,分别是 AppDelegate.h 文件和 AppDelegate.m 文件。
AppDelegate.h 文件如下:
#import
// 引用 IMKit 头文件。
#import "RCIM.h"
// 添加获取用户信息、好友列表和群组信息的 Protocol。
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCIMFriendsFetcherDelegate, RCIMUserInfoFetcherDelegagte, RCIMGroupInfoFetcherDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
AppDelegate.m 文件如下:
#import "AppDelegate.h"
// 引用 IMKit 头文件。
#import "RCIM.h"
// 引用 ViewController 头文件。
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
// 初始化 SDK,传入 App Key,deviceToken 暂时为空,等待获取权限。
[RCIM initWithAppKey:@"e7x8xycsx6flq" deviceToken:nil];
// 设置用户信息提供者。
[RCIM setUserInfoFetcherWithDelegate:self isCacheUserInfo:NO];
// 设置好友信息提供者。
[RCIM setFriendsFetcherWithDelegate:self];
// 设置群组信息提供者。
[RCIM setGroupInfoFetcherWithDelegate:self];
#ifdef __IPHONE_8_0
// 在 iOS 8 下注册苹果推送,申请推送权限。
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
|UIUserNotificationTypeSound
|UIUserNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
// 注册苹果推送,申请推送权限。
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
#endif
// 初始化 ViewController。
ViewController *viewController = [[ViewController alloc]initWithNibName:nil bundle:nil];
// 初始化 UINavigationController。
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:viewController];
// 设置背景颜色为黑色。
[nav.navigationBar setBackgroundColor:[UIColor blackColor]];
// 初始化 rootViewController。
self.window.rootViewController = nav;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
// Register to receive notifications.
[application registerForRemoteNotifications];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
// Handle the actions.
if ([identifier isEqualToString:@"declineAction"]){
}
else if ([identifier isEqualToString:@"answerAction"]){
}
}
#endif
// 获取苹果推送权限成功。
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 设置 deviceToken。
[[RCIM sharedRCIM] setDeviceToken:deviceToken];
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
}
// 获取好友列表的方法。
-(NSArray*)getFriends
{
NSMutableArray *array = [[NSMutableArray alloc]init];
RCUserInfo *user1 = [[RCUserInfo alloc]init];
user1.userId = @"1";
user1.name = @"韩梅梅";
user1.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
[array addObject:user1];
RCUserInfo *user2 = [[RCUserInfo alloc]init];
user2.userId = @"2";
user2.name = @"李雷";
user2.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
[array addObject:user2];
return array;
}
// 获取用户信息的方法。
-(RCUserInfo*)getUserInfoWithUserId:(NSString *)userId
{
if ([@"1" isEqual:userId]) {
RCUserInfo *user = [[RCUserInfo alloc]init];
user.userId = @"1";
user.name = @"韩梅梅";
user.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
return user;
}
if ([@"2" isEqual:userId]) {
RCUserInfo *user = [[RCUserInfo alloc]init];
user.userId = @"2";
user.name = @"李雷";
user.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
return user;
}
return nil;
}
// 获取群组信息的方法。
-(RCGroup*)getGroupInfoWithGroupId:(NSString *)groupId
{
if ([@"1" isEqual:groupId]) {
RCGroup *group = [[RCGroup alloc]init];
group.groupId = @"1";
group.groupName = @"同城交友";
//group.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
return group;
}
if ([@"2" isEqual:groupId]) {
RCGroup *group = [[RCGroup alloc]init];
group.groupId = @"2";
group.groupName = @"跳蚤市场";
//group.portraitUri = @"http://rongcloud-web.qiniudn.com/docs_demo_rongcloud_logo.png";
return group;
}
return nil;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
融云 IMKit SDK 使用 UIViewController 方式实现组件的自定义和调用关系的任意组合,提供 UIVIewController 能力的组件包括会话列表:RCChatListViewController
、群组列表:RCGroupListViewController
、选择好友:RCSelectPersonViewController
、聊天会话:RCChatViewController
、会话设置:RCChatSettingViewController
。
开发者可以通过继承 IMKit SDK 提供的 UI 组件来实现自定义,或者自由组合调用关系:部分 UI 使用融云 SDK,部分UI 由自己开发。例如,好友列表根据自身需求自己实现,其他界面使用融云 SDK 的 UI 组件。
下面以会话列表为例,阐述以继承的方法实现自定义功能。
@interface DemoChatListViewController : RCChatListViewController
@end
-(void)viewDidLoad
{
[super viewDidLoad];
// 自定义导航标题颜色
[self setNavigationTitle:@"会话" textColor:[UIColor whiteColor]];
// 自定义导航左右按钮
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStyleBordered target:self action:@selector(leftBarButtonItemPressed:)];
[leftButton setTintColor:[UIColor whiteColor]];
self.navigationItem.leftBarButtonItem = leftButton;
// 自定义导航左右按钮
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]initWithTitle:@"选择" style:UIBarButtonItemStyleBordered target:self action:@selector(rightBarButtonItemPressed:)];
[rightButton setTintColor:[UIColor whiteColor]];
self.navigationItem.rightBarButtonItem = rightButton;
}
注意导航左右按钮的方法名称,必须是:
leftBarButtonItemPressed
rightBarButtonItemPressed
-(void)leftBarButtonItemPressed:(id)sender
{
[super leftBarButtonItemPressed:sender];
}
-(void)rightBarButtonItemPressed:(id)sender
{
// 跳转好友列表界面,可是是融云提供的 UI 组件,也可以是自己实现的UI
RCSelectPersonViewController *temp = [[RCSelectPersonViewController alloc]init];
// 控制多选
temp.isMultiSelect = YES;
UINavigationController * nav = [[UINavigationController alloc]initWithRootViewController:temp];
// 导航和的配色保持一直
UIImage *image= [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
[nav.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
temp.delegate = self;
[self presentModalViewController:nav animated:YES];
}
-(void)onSelectedTableRow:(RCConversation*)conversation{
if(conversation.conversationType == ConversationType_GROUP)
{
DemoGroupListViewController* groupVC = [[DemoGroupListViewController alloc] init];
self.currentGroupListView = groupVC;
[self.navigationController pushViewController:groupVC animated:YES];
return;
}
// 该方法目的延长会话聊天 UI 的生命周期
DemoChatViewController* chat = [self getChatController:conversation.targetId conversationType:conversation.conversationType];
if (nil == chat) {
chat =[[DemoChatViewController alloc]init];
[self addChatController:chat];
}
chat.currentTarget = conversation.targetId;
chat.conversationType = conversation.conversationType;
//chat.currentTargetName = curCell.userNameLabel.text;
chat.currentTargetName = conversation.conversationTitle;
[self.navigationController pushViewController:chat animated:YES];
}
开发者自己自定义选择好友界面,选择好友之后,需要重载启动私聊(一对一)方法或者重载启动讨论组方法。
/**
* 启动一对一聊天。
*
* @param userInfo
*/
-(void)startPrivateChat:(RCUserInfo*)userInfo{
DemoChatViewController* chat = [self getChatController:userInfo.userId conversationType:ConversationType_PRIVATE];
if (nil == chat) {
chat =[[DemoChatViewController alloc]init];
[self addChatController:chat];
}
chat.currentTarget = userInfo.userId;
chat.currentTargetName = userInfo.name;
chat.conversationType = ConversationType_PRIVATE;
[self.navigationController pushViewController:chat animated:YES];
}
/**
* 启动讨论组。
*
* @param userInfos
*/
-(void)startDiscussionChat:(NSArray*)userInfos{
NSMutableString *discussionName = [NSMutableString string] ;
NSMutableArray *memberIdArray =[NSMutableArray array];
NSInteger count = userInfos.count ;
for (int i=0; i//NSString *name = userinfo.name;
if (i == userInfos.count - 1) {
[discussionName appendString:userinfo.name];
}else{
[discussionName appendString:[NSString stringWithFormat:@"%@%@",userinfo.name,@","]];
}
[memberIdArray addObject:userinfo.userId];
}
// 创建讨论组
[[RCIMClient sharedRCIMClient]createDiscussion:discussionName userIdList:memberIdArray completion:^(RCDiscussion *discussInfo) {
NSLog(@"create discussion ssucceed!");
dispatch_async(dispatch_get_main_queue(), ^{
DemoChatViewController* chat = [self getChatController:discussInfo.discussionId conversationType:ConversationType_PRIVATE];
if (nil == chat) {
chat =[[DemoChatViewController alloc]init];
[self addChatController:chat];
}
chat.currentTarget = discussInfo.discussionId;
chat.currentTargetName = discussInfo.discussionName;
chat.conversationType = ConversationType_DISCUSSION;
[self.navigationController pushViewController:chat animated:YES];
});
} error:^(RCErrorCode status) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"DISCUSSION_INVITE_FAILED %d",status);
UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"" message:@"创建讨论组失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
[alert show];
});
}];
}
在 IMKit 是对 IMLib 的 UI 封装,在 IMKit 中可以直接使用 IMLib 中的所有方法,代码如下:
NSArray *messageArray = [[RCIMClient sharedRCIMClient] getLatestMessages:self.conversationType targetId:self.currentTarget count:10];
更多的融云 SDK UI 组件请参考融云开源的 Demo 例子。
https://github.com/rongcloud/demo-app-ios
应用标识是为了我们的 API 能够正确识别并验证您的应用请求而所必要的信息,对于防止账户盗用和滥用有着重要的作用。针对 iOS 平台,需要填写 Bundle Identifier,在 XCode 中的位置如图所示。
如果您希望您的 iOS 应用程序具备接收推送的能力,您必须要上传 iOS 推送证书。证书生成的方法,请参考:
Cooper's Blog 撰写的 一步一步实现 iOS 应用 PUSH 功能
或
风雨雷电堂 撰写的 苹果推送通知服务教程 Apple Push Notification Services Tutorial
讨论组人数在服务端有上限限制,为 500 人,在客户端,根据具体的业务需求,可以通过配置文件配置讨论组人数上限,配置的方法如下:
设置定义在 RCSelectPersonViewController.h 文件中,开发时请设置相关值:
/**
* 讨论组人员最大限制,默认50个
*/
@property (nonatomic,assign) NSInteger discussion_members_limit;
为了您能够更好的理解如何使用融云 IMKit SDK,我们在 GitHub 上提供了开源的 Demo App。
请移步访问:
https://github.com/rongcloud/demo-app-ios
https://github.com/rongcloud/demo-server-php
https://github.com/rongcloud/demo-server-nodejs