美文网首页iOS之常用第三方库的实用牛叉的demoiOS学霸笔记
LeanCloud实时通信模块iOS端快速接入指南(二)

LeanCloud实时通信模块iOS端快速接入指南(二)

作者: _奔跑的炸鸡 | 来源:发表于2016-02-23 15:47 被阅读1827次

2016年03月03日更新

使用id A进入聊天,然后返回登陆界面使用id B进入聊天,然后对A发起会话会导致崩溃,原因是没有关闭A的客户端,会导致自己和自己发起会话。解决方法是在开启聊天客户端之前先关闭之前的客户端,即改写『登陆』的事件为下列代码
- (IBAction)loginBtnClicked:(id)sender {
[[CDChatManager manager]closeWithCallback:^(BOOL succeeded, NSError *error) {
[[CDChatManager manager]openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) {
ChatListViewController * chatList = [[ChatListViewController alloc]init];
[self.navigationController pushViewController:chatList animated:YES];
}];

 }];

}

写在最前面

更新了最新版的LeanCloud的SDK
静态库的体积确实小了很多,但是有一些LeanCloud改了一小部分方法的名称
如果按照我的攻略发现代码有问题的,请把所有的Conv改为Conversation不管这个Conv是在开头还是结尾还是方法名中间

比如老版的是

  [[CDChatManager manager] fetchConvWithOtherId:_textField.text callback:^(AVIMConversation *conversation, NSError *error) {
    }];

现在就是

[[CDChatManager manager]fetchConversationWithOtherId:@"78" callback:^(AVIMConversation *conversation, NSError *error) {
    }];

其他方法同上,如有其它发现我都会写在这里
另外老版的CDUserModel协议已经更名为CDUserModelDelegate

  • LeanCloud的程序员一定是强迫症晚期(╯‵□′)╯︵┻━┻

写在前面

首先附上之前文章的链接
[LeanCloud实时通信模块IOS端快速接入指南(一)]
废话少说,这一节我们来实现一个相对完整的聊天功能。


功能描述

还记得上一节说过的LeanCloud如何创建聊天吗?没错,你自己的id加上你要聊天的人的id就可以创建一个对话。
那么我们今天做这么一个东西,项目启动时输入一个自己的id,确认后弹出类似QQ的最近聊天界面,点击最近聊天的任意会话进行聊天或对任意指定id发起聊天。

正文

准备项目

新建一个项目,起一个你喜欢的名字


初始化项目

然后是导入SDK,在AppDelegate中注册,和前边一样


Paste_Image.png
搭建页面结构

这里我们准备的项目在下一节还要继续用,所以我们使用StoryBoard搭建一个相对完整的项目

*为了尽量照顾大多数人,我这里把构建StoryBoard的过程也贴出来,已经熟练使用的请忽略

删除自带的ViewController和Main.storyboard中对应的控件
在Main.storyboard中添加一个标签栏控制器(TabBarViewController)并设置为根视图控制器(勾选Is Initial View Controller选项,被设置为根视图控制器的控件左边会有箭头)

设置标签栏

去掉标签栏自带的两个视图控制器,更换成导航视图控制器(NavigationController)
按住鼠标左键不动从标签栏拖动到导航栏


添加关联

松开鼠标后选择ViewControlers

添加关联

另一个导航栏一样照做
运行项目,如下图所示

Paste_Image.png
搭建登陆界面

前一篇说过,我们使用[CDChatManager manager] openWithClientId:@"Tom" callback:^(BOOL succeeded, NSError *error) {}];方法只需要一个自定义的ClientId就可以登陆一个聊天客户端
因此第一个界面我们就用来输入这个Id。
由于在StoryBoard中导航栏自带的根视图控制器默认是UITableVIewController,所以我们删掉它,换成普通的视图控制器
并给它一个标题--『登陆』

登陆界面

登陆界面很简单,如下所示

Paste_Image.png

新建一个视图控制器并将其和StroyBoard中的登陆界面关联起来

Paste_Image.png
实现聊天

给登陆按钮添加事件之前我们先创建接下来要跳转的界面--最近聊天列表ChatListViewController,继承于CDChatListVC

Paste_Image.png
在LoginViewController中引入头文件
#import <CDChatManager.h>
#import"ChatListViewController.h"
按钮的点击事件这么写
- (IBAction)loginBtnClicked:(id)sender {
[[CDChatManager manager]openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) {
ChatListViewController * chatList = [[ChatListViewController alloc]init];
[self.navigationController pushViewController:chatList animated:YES];
}];
}
  • 这里解释一下这个CDChatListVC,和前一篇用到的CDChatRoomVC一样,这也是LeanChatLib中写好的一个类,继承于UITableVIewController,每个cell代表一个会话,第一次进入或者刷新会拉取最近的会话,获取到一个叫做conversations的数组,然后将conversation作为数据源读出每一个会话然后展示。点击会话则进入聊天。我们将在下一节详细讲解他的方法并按照我们的需求加以改造,所以这里我们只需要先知道它是干嘛的就够了。

刚才说了,这个ChatListViewController是一个UITableVIewController,所以我们对它稍加改造,给它的TableView加一个HeaderView。
在它的viewDidLoad中这么写
- (void)viewDidLoad {
[super viewDidLoad];

UIView * headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 60)];
self.tableView.tableHeaderView = headerView;

_textField = [[UITextField alloc]initWithFrame:CGRectMake(15, 5, self.view.bounds.size.width - 30, 25)];
_textField.layer.borderColor = [UIColor lightGrayColor].CGColor;
_textField.layer.borderWidth = 1;
[headerView addSubview:_textField];

UIButton * startChat = [UIButton buttonWithType:UIButtonTypeSystem];
startChat.frame = CGRectMake(60, 35, self.view.bounds.size.width - 120, 20);
[startChat setTitle:@"开始聊天" forState:UIControlStateNormal];
[headerView addSubview:startChat];
[startChat addTarget:self action:@selector(startChatClicked:) forControlEvents:UIControlEventTouchUpInside];

}

在添加按钮的点击事件之前我们要向之前一样,去创建一个继承于CDChatRoomVC的ChatRoomViewController。

创建聊天室

把聊天室引入到聊天列表
#import "ChatRoomViewController.h"
然后是按钮的点击事件
- (void)startChatClicked:(UIButton *)btn
{
if(_textField.text.length > 0)
{
[[CDChatManager manager] fetchConvWithOtherId:_textField.text callback:^(AVIMConversation *conversation, NSError *error) {
ChatRoomViewController * chatRoom = [[ChatRoomViewController alloc]initWithConv:conversation];
[self.navigationController pushViewController:chatRoom animated:YES];
}];
}

}

因为标签栏会遮住聊天室下方的输入控件,所以我们这么做
在ChatListViewController中添加方法
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.tabBarController.tabBar.hidden = NO;
}
在ChatRoomViewController中添加方法
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.tabBarController.tabBar.hidden = YES;
}

到此为止我们已经实现了前面的需求,运行项目
在登录界面输入你的id

登陆

点击登陆后输入你想聊天的人的id,然后点击开始聊天

寻找聊天对象

出现如下界面

聊天界面

点击返回

返回最近聊天列表

然后你会发现,卧槽?说好的最近聊天呢? 怎么一篇空白?别急,接下来我们就解决这个问题。

显示最近聊天

刚才点返回的时候,控制台会给你报一堆警告

控制台警告

前面说过,你第一次进入最近聊天页或者刷新最近聊天的时候会拉取到最近的会话,但是你拉取的是会话,和你聊天的对象的头像昵称等信息并没有包含在会话对象中,你需要从CDChatManager的代理中获取到这些信息。因此我们需要实现CDChatManager的CDUserDelegate。这个代理会返回一个遵循CDUserModel协议的对象。

创建一个继承于NSObject的UserFactory类

UserFactory
引入头文件
#import <LeanChatLib/LeanChatLib.h>
遵守协议
@interface UserFactory : NSObject <CDUserDelegate>

@end

在UserFactory.m中实现代理方法
为了方便我们把遵循CDUserModel协议的类也在这里声明

#import "CDUserFactory.h"

@interface CDUser : NSObject <CDUserModel>

@property (nonatomic, strong) NSString *userId;

@property (nonatomic, strong) NSString *username;

@property (nonatomic, strong) NSString *avatarUrl;

@end

@implementation CDUser

@end

@implementation UserFactory

#pragma mark - UserDelegate


- (void)cacheUserByIds:(NSSet *)userIds block:    (AVBooleanResultBlock)block {
block(YES, nil); 
}

- (id <CDUserModel> )getUserById:(NSString *)userId {
CDUser *user = [[CDUser alloc] init];
user.userId = userId;
//在cell中显示的聊天对象的名字
user.username = userId;
//聊天对象的头像
user.avatarUrl = @"http://tp2.sinaimg.cn/5088940253/180/5745995456/1";
return user;
}

@end

然后在Appdelegate.m中添加代理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[CDChatManager manager].userDelegate = [[UserFactory alloc]init];
...
return YES;
}

然后再次运行项目,输入刚才的ID,这个时候我们的最近聊天列表就出现了

成功
  • 头像不显示的同学请检查是否打开了ATS。iOS 9 之后默认开启ATS,无法使用Http请求
    关闭方法为在info.plist中添加字段
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>

接下来我们要做的是实现点击最近会话进入聊天
首先让ChatListViewController遵循协议
interface ChatListViewController ()<CDChatListVCDelegate>

然后在viewDidLoad方法中添加加上一句
self.chatListDelegate = self;

然后实现代理方法
- (void)viewController:(UIViewController *)viewController didSelectConv:(AVIMConversation *)conv
{
ChatRoomViewController * chatRoom = [[ChatRoomViewController alloc]initWithConv:conv];
[self.navigationController pushViewController:chatRoom animated:YES];
}
再运行试试,点击最近的聊天也可以进入聊天了


总结

到此为止,我们就利用LeanCloud搭建了一个相对完整的聊天,你已经可以用这个东西跟你的小伙伴聊天了。
虽然我写了这么多乱七八糟的东西,其实总计一下我们只用了三个类就实现了这全部的东西。
这里我们回顾一下

三个类:
  • CDChatRoomVC:LeanChatLib提供的聊天室。拥有带Conversation参数的构造方法,声明后直接跳转进来即可。
  • CDChatListVC:LeanChatLib提供的聊天列表类,登陆聊天Client后直接跳转进入或者进入后再登陆Client都可以。
  • CDChatManager:LeanChatLib的核心管理类,通过[CDChatManager manager]获取单例。它的两个重要方法:
    //登陆一个聊天客户端 openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) { };
    //获取一个单聊会话 fetchConvWithOtherId:@"78" callback:^(AVIMConversation *conversation, NSError *error) { }

为了方便理解,这里再多嘴提一句,第一个方法,openClientId。既然有open,对应的也有一个close方法用来关闭聊天客户端。我们所开启的这个Client,不像我们学的Button,Label一样,依附于父视图,父视图销毁,它们也跟着销毁。Client除非你主动关闭或者直接关掉程序,执行open之后它会一直在后台处于开启状态。这也就意味着,只要你执行了openClient,你可以在程序的任意一个界面执行fetchConv获取到一个会话然后跳转到聊天,并不一定是在最近聊天列表才能这么做。这样就能很方便灵活的使用即时通讯模块。


这一节到此结束,下一节,我们来学习按照自己的需求改造我们的聊天功能。

相关文章

网友评论

  • db5c33f24d60:你好博主,为什么我的聊天室页面和最近聊天列表不出现内容
  • 小豪学科技:你好博主,我想要实现对话时候的头像显示各自自己的头像怎么实现呢,做了好久也没实现,只能显示一种头像,我想要显示对话双方的头像
    小豪学科技:@8f20c5d4faef 解决了
    8f20c5d4faef:@子豪爱swift 大神解决了吗? 能不能加下我QQ1667209497
  • 刘开心ya:您能告诉我 我用最新版的SDK 需要添加哪些依赖库? 我这里为什么总报错呢
    _奔跑的炸鸡:@你敲什么呐i 用pod导入的话应该是不需要手动添加依赖库的
  • 362404cab449:我下了你的demo,就是A和B对话是,B回信息时会出现两条一样的,返回最近联系人界面后,再点击进去,就显示一条信息正常了
    362404cab449:@_奔跑的炸鸡 哦 ,好的,还有第四季吗?
    _奔跑的炸鸡:@我的天啊 我只是做功能演示 实际项目中要考虑的问题要多得多 所以难免存在BUG
  • 362404cab449:在登陆界面的点击事件添加closeWithCallback的方法后,就不跳转了
    _奔跑的炸鸡:@我的天啊 建议你把Demo下载下来看 最后一篇的最后有地址
    _奔跑的炸鸡:@我的天啊 先关闭再开启 你先确认你的代码是否一样
  • DamonLu:请问CDUser 是怎么来的呢
    _奔跑的炸鸡:@SEIRIN_KAGAMI 为了证明我不是强迫症િ😳ી
    DamonLu:@_奔跑的炸鸡 OK~ 你的名字后面为啥不加个 _ 呢
    _奔跑的炸鸡:@SEIRIN_KAGAMI CDUser只是一个名字,你可以起任何名字,ABC,BCA都可以,只要它继承自NSObject且实现了CDUserModel的代理。
  • joan_:它是怎么获取用户的头像的呢
    _奔跑的炸鸡:@JoanW 下一节说😌😌😌😌
    joan_:那怎么发图片呢
    _奔跑的炸鸡:@JoanW 通过CDChatManager的代理方法返回啊
  • joan_:聊天中怎么发图片呢?
  • 4f002d4502b5:跟着敲了一遍,感觉蛮好玩的
    支持!
    _奔跑的炸鸡:@反方向de钟 嗯😉谢谢支持 请关注后续内容
  • qiongyong:什么时候下一节啊 :smile:
    _奔跑的炸鸡:@qiongyong有空就写,估计下周发
  • iOS程序犭袁:强迫症说得就是我
    _奔跑的炸鸡:@iOS程序犭袁 没有强迫症的程序员不是好程序员😠😠😠😠

本文标题:LeanCloud实时通信模块iOS端快速接入指南(二)

本文链接:https://www.haomeiwen.com/subject/lrgmkttx.html