首页 > 代码库 > 点对点聊天吧

点对点聊天吧

概要

瞎逛发现某广告的链接,点进去,发现某通讯SDK,瞅了下,好像不是太复杂,想想也算学了些IOS开发,好像没啥事做,拿来学学学习。

该SDK支持Cocoapod第三方库,所以安装比较简单的,不过注意只能使用两个库中的一个,因为IMKit包含了IMLib,其中IMLib是通讯库,没有实现界面组件,而IMKit在IMLib的基础上实现了界面,集成简单。

本例子力求简单点吧,做了一个好友聊天功能,同时加了个客服功能,直接集成IMKit到应用。

结果展示

技术分享


主要技术点

  • 新建single工程,然后关闭工程,到工程的根目录下新建Podfile文件,在文件中添加
    pod 'RongCloudIMKit'
    然后使用命令
    pod install
    安装通讯库,然后生成.xcworkspace工程文件,此后所有的开发工作在此工程里面进行,直接使用XCode打开就好(其实这一步就是使用CocoaPod新建一个工程)
  • 在AppDelegate.m文件中完成APP初始化,需要引入融云的头文件RCIM.h,使用initWithAppKey:deviceToken:APP Key完成融云应用的初始化,只需要初始化一次就好了,然后注册推送通知(虽然本程序没有示例推送),其主要代码如下所示
    // 初始化 SDK,传入 App Key,deviceToken 暂时为空,等待获取权限。
    [RCIM initWithAppKey:@"c9kqb3rdk7jjj" 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
  • 因为聊天时候需要切换视图,所以应该要使用导航视图控制器,所以需要将程序的根视图控制器修改为导航视图控制器。其主要代码如下所示
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // 视图放在导航控制器里面,然后子视图能够通过导航切换视图
    // 如果是标签栏控件作根视图控制器,可给每个标签定义一个导航控制器
    ViewController* viewController = [[ViewController alloc] init];
    UINavigationController* navController = [[UINavigationController alloc] init];
    [navController addChildViewController:viewController];
    
    // 设置跟视图控制器
    self.window.rootViewController = navController;
  • 好友列表使用UITableView展现,因为没有服务器,所以好友列表直接在程序里面模拟获取,每个好友包括好友ID、好友名字、好友头像,如果要使用某个用户登录,需要获取某个用户的认证令牌(其规范流程是,APP客户端程序使用用户信息和APP Key向APP服务器发起令牌请求,APP服务器使用本地存储的Secret Key和APP客户端的请求信息融云服务器请求令牌,然后融云服务器向APP服务器返回令牌,APP服务器再将该令牌返回给客户端),可使用融云应用配置里面的API调试功能直接生成令牌,然后在客户端使用该令牌可登录系统。使用Token登录认证的主要代码如下所示
    - (void)login:(NSString*)token
    {
        // 连接融云服务器。
        [RCIM connectWithToken:token completion:^(NSString *userId)
        {
            // 此处处理连接成功。
            NSLog(@"Login successfully with userId: %@.", userId);
        } error:^(RCConnectErrorCode status)
        {
            // 此处处理连接错误。
            NSLog(@"Login failed.");
        }];
    }
    其中token是请求获取的令牌。
  • 好友列表展示使用UITabView,展现的头像直接使用网络地址也是可以的,如下所示
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell* cell = nil;
        NSString* kCellID = @"friend";
        
        cell = [_tableView dequeueReusableCellWithIdentifier:kCellID];
        if(cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellID];
        }
        
        RCUserInfo* user = [_frindList objectAtIndex:indexPath.row];
        cell.textLabel.text = user.name;
        NSString* url = [user.portraitUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[[NSURL alloc] initWithString:url]]];
        
        return cell;
    }
  • 当点击某个好友时,需要打开与该好友的单聊界面,这里的UI直接使用融云集成的UI,所以主要代码如下所示
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [_tableView deselectRowAtIndexPath:indexPath animated:YES];
        
        UIViewController* chatController = nil;
        RCUserInfo* user = [_frindList objectAtIndex:indexPath.row];
        
        if([user.userId isEqualToString:@"kf"])
        {
            // 创建客服聊天视图控制器。
            RCChatViewController *chatViewController = [[RCIM sharedRCIM]createCustomerService:@"KEFU1420640265290" title:user.name completion:^()
            {
                // 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
            }];
            
            chatController = (UIViewController*)chatViewController;
        }
        else
        {
            // 创建单聊视图控制器。
            RCChatViewController *chatViewController = [[RCIM sharedRCIM] createPrivateChat:user.userId title:user.name completion:^()
            {
                // 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
            }];
            
            chatController = (UIViewController*)chatViewController;
        }
        // 把视图控制器添加到导航栈。
        [self.navigationController pushViewController:chatController animated:YES];
    }
  • 需要支持客服的话,需要在融云系统里的应用配置的功能模块开启,主要是验证客户管理员邮箱及设置密码,然后获取客户的customerServiceId,这样在用户与客服通讯时,传入该值,即可与客服通信,主要代码见上面好友的单聊中。

主要代码

//
//  ViewController.m
//  RCDemo
//
//  Created by God Lin on 15/1/7.
//  Copyright (c) 2015年 arbboter. All rights reserved.
//

#import "ViewController.h"
// 融云头文件
#import "RCIM.h"

#define USER_JJF @"Un/MhUnZaA7mN9KPIMqFjsOWN+Jz2/18SGCwCc9gCOoB8MIFranJjJgCDBD53R3Jc7rSCaUdONXk/CvO9+uPKA=="

@interface ViewController () <UITableViewDataSource, UITableViewDelegate,RCIMFriendsFetcherDelegate, RCIMUserInfoFetcherDelegagte, RCIMGroupInfoFetcherDelegate>

@property (nonatomic, strong) UITableView* tableView;
@property (nonatomic, strong) NSMutableArray* frindList;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    _frindList = [NSMutableArray arrayWithArray:[self getFriends]];
    _tableView = [[UITableView alloc] initWithFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+20, self.view.frame.size.width, self.view.frame.size.height-20)];
    _tableView.tableFooterView= [[UITableView alloc] init];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    [self.view addSubview:_tableView];
    
    [self login:USER_JJF];
}

- (void)login:(NSString*)token
{
    // 连接融云服务器。
    [RCIM connectWithToken:token completion:^(NSString *userId)
    {
        // 此处处理连接成功。
        NSLog(@"Login successfully with userId: %@.", userId);
    } error:^(RCConnectErrorCode status)
    {
        // 此处处理连接错误。
        NSLog(@"Login failed.");
    }];
}

#pragma 融云协议
// 获取好友列表的方法。
-(NSArray*)getFriends
{
    NSMutableArray *array = [[NSMutableArray alloc]init];
    
    RCUserInfo *user = [[RCUserInfo alloc]init];
    user.userId = @"jjf";
    user.name = @"吉*峰";
    user.portraitUri = @"http://pic.sc.chinaz.com/Files/pic/icons128/5329/13233.png";
    [array addObject:user];
    
    /** 可继续添加 */
    
    user = [[RCUserInfo alloc]init];
    user.userId = @"kf";
    user.name = @"在线客服";
    user.portraitUri = @"http://pic.sc.chinaz.com/Files/pic/icons128/4919/2.png";
    [array addObject:user];

    return array;
}
- (void)getUserInfoWithUserId:(NSString *)userId completion:(void(^)(RCUserInfo* userInfo))completion
{
    for (NSInteger i=0; i<_frindList.count; i++)
    {
        RCUserInfo* user = [_frindList objectAtIndex:i];
        if([user.userId isEqualToString:userId])
        {
            completion(user);
            break;
        }
    }
}

-(void)getGroupInfoWithGroupId:(NSString*)groupId completion:(void(^)(RCGroup* groupInfo))completion
{
    
}
#pragma 协议UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_frindList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell* cell = nil;
    NSString* kCellID = @"friend";
    
    cell = [_tableView dequeueReusableCellWithIdentifier:kCellID];
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellID];
    }
    
    RCUserInfo* user = [_frindList objectAtIndex:indexPath.row];
    cell.textLabel.text = user.name;
    NSString* url = [user.portraitUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[[NSURL alloc] initWithString:url]]];
    
    return cell;
}
#pragma 协议UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [_tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    UIViewController* chatController = nil;
    RCUserInfo* user = [_frindList objectAtIndex:indexPath.row];
    
    if([user.userId isEqualToString:@"kf"])
    {
        // 创建客服聊天视图控制器。
        RCChatViewController *chatViewController = [[RCIM sharedRCIM]createCustomerService:@"KEFU1420640265290" title:user.name completion:^()
        {
            // 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
        }];
        
        chatController = (UIViewController*)chatViewController;
    }
    else
    {
        // 创建单聊视图控制器。
        RCChatViewController *chatViewController = [[RCIM sharedRCIM] createPrivateChat:user.userId title:user.name completion:^()
        {
            // 创建 ViewController 后,调用的 Block,可以用来实现自定义行为。
        }];
        
        chatController = (UIViewController*)chatViewController;
    }
    // 把视图控制器添加到导航栈。
    [self.navigationController pushViewController:chatController animated:YES];
}
@end

项目工程

点对点聊天吧