iOS集成环信后,手机正在运行的程序怎么关闭在后台为什么不掉用didreceivemessage方法

1. pod引入的Hyphenate里面的.h文件中和手动下载的sdk相比会缺少Hyphenate.h 。A : &主要是pod 问题 本地仓库太旧了, 终端行pod repo update, 之后在pod search 'Hyphenate' 如果可以找到3.3.0版本, 就可以下载了 podfile 里面 platform
要指定8.02.&iOS SDK 从低版本 升到3.3.0 后运行报错dyld: Library not loaded: @rpath/Hyphenate.framework/Hyphenate& Referenced from: /Users/white/Library/Developer/CoreSimulator/Devices/BE0DDC26-96AE--48DC6938042B/data/Containers/Bundle/Application/4F9F570A-44B5-4F81-AD19-F7AA38D26E40/SYSchoolProject.app/SYSchoolProject& Reason: image not foundA :&在Build setting -& General这里加上。&还有这里也加上 改不能成optional3.在AppDelegate中执行[EaseMob
sharedInstance]崩溃A :&other link flags添加“-ObjC”选项(注意:O和C大写)4.在消息提示的小红点问题。在UITabBarController的子类中设置了IChatManagerDelegate,但是setupUnreadMessageCount不回A :&在AppDelegate中没有写如下代码[objc]&view
plain&copy&print?
上一篇: 下一篇:你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
期间 出现过一次 走 didReceiveRemoteNotification 的 但是不知道 啥情况会进来。。。我记得好像是把换信注册 的那堆 东西给删了。。而我项目默认是 使用JPUSH 的
所以 好像就走了 didReceiveRemoteNotification
求高手回答下
这个看方法名我们也能理解,didReceiveLocalNotification是本地通知会触发的方法,当点击通知横幅进入app时会调用;didReceiveRemoteNotification是离线推送触发的方法,当点击通知横幅进入app时会调用。
刚试了一下 模拟登出 发现消息 不接收了。。所以 还是不知道 怎么才能进 remote
要回复问题请先或
浏览: 2089
关注: 2 人
知识价值的认可,源自您的赞赏
扫描二维码,你的支付将由imGeek代收后转给对方
感谢您的赞赏
一个开放、互助、协作、创意的社区
一个开放、互助、协作、创意的社区
京ICP备号-3关于集成环信的UI中遇到的一些坑 - 简书
关于集成环信的UI中遇到的一些坑
其实环信集成大体上不是很难,但是有几个注意点。首先,我集成的是环信3·0,官网上的文档跟实际的api稍稍有点区别,但凑合凑合大致还是能看的。首先我们看一下如何集成登录以及集成登录的时候遇到的问题:
[[EMClient sharedClient] loginWithUsername:self.userNameField.text password:self.passwordField.text completion:^(NSString *aUsername, EMError *aError) {}];
// [[EMClient sharedClient] addDelegate:self delegateQueue:nil];
当我们设置当前控制器为代理的时候,这里跟以前设置代理属性稍稍有点不一样,说到这里,必须要提到一个概念“多播代理”,集成环信的时候,大部分的api基本都是以代理方法来实现,环形本来也是基于XMPPFramework框架来开发的,很早之前,在XMPPFramework就接触过这个多播代理,我们以前所理解的代理可能就是控制器之间的逆向传值,这个是属于一对一的,也就是说只能有一个对象成为我的代理,这里的“多播代理”的唯一区别就是代理对象可以有很多个, 只要当前控制器设置了代理属性,那么当执行这个代理方法的时候,遵循这个代理属性的控制器就会调用这个代理方法。这里的一个注意点就是添加代理一定不要忘了移除代理,这个暂且算一个小小的注意点。
- (void)dealloc {
[[EMClient sharedClient] removeDelegate:self];
那么继续往下看,环信还提供给我们了自动登录的功能,也就是说只要第一次登录成功以后,环信里面会把登录成功的账号和密码都保存在本地,具体的我也看了一下沙盒中的文件:
15.11.42.png
可以看到这个是以plist文件存储的,而且是放在Library/Preferences文件夹下,于是我大胆猜想,这个应该是使用[NSUserDefaults standardUserDefaults]这种存储方法实现的。当然了这个并不重要我们继续看环信提供给我们的api
[EMClient sharedClient].options.isAutoLogin
上面这个方法其实取值就是从而本地取值,对应的就是上面截图中的emAutoLogin属性对应的值。我们做自动登录的时候的逻辑,比如我的demo中的逻辑是这样的:当我第一次登录的时候,这个时候isAutoLogin的属性为NO,加载登录界面,当我退出以后,在后台将这个应用程序退出(杀死),这时候我们再次进入,此时isAutoLogin的属性值为Yes那么我们直接加载主界面,说到这里有一个问题当我们自动登录的时候,是向服务器发送的异步请求,只有当我们自动登录成功以后,才会去显示主界面,才会去加载“联系人列表”“会话列表”等。我们怎么知道自动登录是否成功?别着急,往下看在环信的官网文档上也能看到环形给我们提供了一个代理方法,当我们自动登录无论是否成功,都会回调这个代理方法。
#pragma mark - 发生自动登录的时候回调用该方法
- (void)autoLoginDidCompleteWithError:(EMError *)aError {
// 隐藏菊花
[MBProgressHUD dh_hideIndicatorForView:self.view];
if (!aError) {
NSLog(@"自动登录");
// 展示错误信息
[MBProgressHUD dh_showInfoWithTitle:@"登录提示" subTitle:aError.errorDescription toView:self.view afterDelay:.5];
至于上面方法中的逻辑因项目而异。仅供参考、说完登录这块以后,下面就要说说联系人列表了,环信的EaseUI提供了联系人列表,但是我这里没有集成UI,我使用的自定义的UI,关于联系人列表这块主要使用的是以下代理
// 添加代理
[[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];
关于联系人列表这块根据官方文档提供的api大致可以集成,比较简单,我在集成的过程中也没有碰到什么问题,所以这里不作细说。
哦,其实说到这里还有一个问题,当我们集成环信的EaseUI的时候,把EaseUI拖进来的时候会报错:如下:
15.39.56.png
其实碰到上面这个问题还是很好解决的,这个是因为用到了UIKit里的类,但是只导入了Foundation框架,这个错误在其他类里也会出现,我们可以手动修改Founfation为UIKit,但是我不建议这么做,第一这个做法的工程量比较大, 在其他类里面也要导入,二,不利于移植,当以后环信更新的时候我们还是需要做同样的操作,这里我的做法的创建一个pch文件,在pch文件里面导入UIKit。
说到这里又要多说一句了,在Xcode6.x之前,创建一个新的iOS工程的时候 会pch文件默认就会被创建,但是自从Xcode6.x(具体版本我也不太清楚)以后pch文件就被取消了,如果要用到,需要用户自动创建,苹果官方取消这一文件,至少说明一个道理,苹果不推荐开发者使用pch文件,这是因为我们如果把大量的文件都写在pch文件里面,那么当程序启动的时候会去把pch中引入的头文件都去加载到内存中,这样以来就会造成,编译很慢,程序启动很慢。所以我们应该尽量避免在使用pch文件的时候导入大量的框架或者文件。
上面说到了集成UI,在环信提供给我们的UI中需要依赖如下第三方库:
15.55.48.png
为什么要说这个呢?我在集成这个UI之前,就已经使用cocoapods导入了MBprogressHUD,这里又引入EaseUI,就会造成冲突,这个时候的解决方法其实很简单:把EaseUI中的MBProgressHUD删除就可以了,如下所示:
最后,当我们集成“聊天列表”的时候写了如下代码
#pragma tableView的代理方法----监听每一行的点击
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 获取当前好友
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// 跳转控制器
EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:cell.textLabel.text conversationType:EMConversationTypeChat];
[self.navigationController pushViewController:chatController animated:YES];
[self.navigationController showViewController:chatController sender:nil];
额,好像就可以了~ 就是这么简单还有一个就是会话列表了“EaseConversationListViewController”集成这个的时候稍稍有点坑。我继承自这个控制器DHConversationController,在这个里面试着去调用环信暴露出来的代理方法,数据源方法等,发现都不调用,根本就不走代理方法, 界面也不显示。解决办法如下:在DHConversationController添加如下代码就可以了
- (void)viewDidLoad {
[super viewDidLoad];
[self tableViewDidTriggerHeaderRefresh];
就是这么神奇,集成到这里语音聊天,地图等功能大部分都是比较好使的,但是还是有一些小小的问题我会慢慢去完善。最后附上我的demo链接:由于作者水平有限,能力一般,肯定还有很多不足之处,恳请各位看官批评指正~Over
nothings gonna change my love for youiOS即时通讯-环信API的使用总结 - 简书
iOS即时通讯-环信API的使用总结
环信SDK的使用
在苹果开发者网站进行制作推送证书
制作推送证书时需根据开发环境不同申请所需的证书类型:
1)对于开发环境(sandbox)的推送证书,请选择 Apple Push Notification service SSL (Sandbox)2)对于生产环境(production)的推送证书,请选择 Apple Push
Notification service SSL (Production)
证书申请完之后下载并用钥匙串打开导出为P12格式.
登录环信管理后台,创建应用,将对应的信息填写完整后,上传在苹果开发者账号中申请的推送证书
环信SDK的导入
1)手动导入:从环信官网下载HyphenateLite SDK 导入到工程目录中,并添加所需的依赖库;
2)自动导入:用cocopods导入,在工程中创建podfile文件,并pod ‘HyphenateLite_CN’;
环信SDK的基础功能
配置聊天账号
a.初始化SDK 第一步: 引入相关头文件 #import &HyphenateLite/EMSDK.h&。 第二步: 在工程的 AppDelegate 中的以下方法中,调用 SDK 对应方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//AppKey:注册的AppKey,详细见下面注释。
//apnsCertName:推送证书名(不需要加后缀),详细见下面注释。
EMOptions *options = [EMOptions optionsWithAppkey:@"douser#istore"];
options.apnsCertName = @"istore_dev";
[[EMClient sharedClient] initializeSDKWithOptions:options];
return YES;
// APP进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application
[[EMClient sharedClient] applicationDidEnterBackground:application];
// APP将要从后台返回
- (void)applicationWillEnterForeground:(UIApplication *)application
[[EMClient sharedClient] applicationWillEnterForeground:application];
EMError *error = [[EMClient sharedClient] registerWithUsername:@"8001" password:@"111111"];
if (error==nil) {
NSLog(@"注册成功");
EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"];
if (!error) {
NSLog(@"登录成功");
d.自动登录
BOOL isAutoLogin = [EMClient sharedClient].options.isAutoL
if (!isAutoLogin) {
EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"];
SDK连接服务器的状态变化时会接收到该回调
有以下几种情况,会引起该方法的调用:
1. 登录成功后,手机无法上网时,会调用该回调
2. 登录成功后,网络状态变化时,会调用该回调
@param aConnectionState 当前状态
- (void)didConnectionStateChanged:(EMConnectionState)aConnectionS
f.退出登录
EMError *error = [[EMClient sharedClient] logout:YES];
if (!error) {
NSLog(@"退出成功");
g.被动退出登录
当前登录账号在其它设备登录时会接收到该回调
- (void)didLoginFromOtherD
当前登录账号已经被从服务器端删除时会收到该回调
- (void)didRemovedFromS
快速集成群聊功能
a.创建群组
EMError *error =
EMGroupOptions *setting = [[EMGroupOptions alloc] init];
setting.maxUsersCount = 500;
setting.style = EMGroupStylePublicOpenJ// 创建不同类型的群组,这里需要才传入不同的类型
EMGroup *group = [[EMClient sharedClient].groupManager createGroupWithSubject:@"群组名称" description:@"群组描述" invitees:@[@"6001",@"6002"] message:@"邀请您加入群组" setting:setting error:&error];
if(!error){
NSLog(@"创建成功 -- %@",group);
b.初始化聊天界面(需导入EaseUI)
//群ID:@"groupId"
//聊天类型:EMConversationTypeGroupChat
EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:@"groupId" conversationType:EMConversationTypeGroupChat];
快速集成好友功能
a.添加好友
[[EMClient sharedClient].contactManager addContact:@"8001"
message:@"我想加您为好友"
completion:^(NSString *aUsername, EMError *aError) {
if (!aError) {
NSLog(@"邀请发送成功");
//同意好友申请
[[EMClient sharedClient].contactManager approveFriendRequestFromUser:@"8001"
completion:^(NSString *aUsername, EMError *aError) {
if (!aError) {
NSLog(@"同意好友成功");
//拒绝好友申请
[[EMClient sharedClient].contactManager declineFriendRequestFromUser:@"8001"
completion:^(NSString *aUsername, EMError *aError) {
if (!aError) {
NSLog(@"拒绝好友成功");
b.删除好友
// 删除好友
[[EMClient sharedClient].contactManager deleteContact:@"8001"
completion:^(NSString *aUsername, EMError *aError) {
if (!aError) {
NSLog(@"删除成功");
c.获取好友
//从服务器获取所有的好友
[[EMClient sharedClient].contactManager getContactsFromServerWithCompletion:^(NSArray *aList, EMError *aError) {
if (!aError) {
NSLog(@"获取成功");
//从数据库获取所有的好友
NSArray *userlist = [[EMClient sharedClient].contactManager getContacts];
a.构造文字消息
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要发送的消息"];
NSString *from = [[EMClient sharedClient] currentUsername];
//生成Message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
b.构造图片消息
EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:data displayName:@"image.png"];
NSString *from = [[EMClient sharedClient] currentUsername];
//生成Message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
c.构造语音消息
EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:@"audioPath" displayName:@"audio"];
body.duration =
NSString *from = [[EMClient sharedClient] currentUsername];
// 生成message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
d.构造视屏消息
EMVideoMessageBody *body = [[EMVideoMessageBody alloc] initWithLocalPath:@"videoPath" displayName:@"video.mp4"];
NSString *from = [[EMClient sharedClient] currentUsername];
// 生成message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
e.构造文件消息
EMFileMessageBody *body = [[EMFileMessageBody alloc] initWithLocalPath:@"filePath" displayName:@"file"];
NSString *from = [[EMClient sharedClient] currentUsername];
// 生成message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
f.构造透传消息
EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:action];
NSString *from = [[EMClient sharedClient] currentUsername];
// 生成message
EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
message.chatType = EMChatTypeC// 设置为单聊消息
//message.chatType = EMChatTypeGroupC// 设置为群聊消息
//message.chatType = EMChatTypeChatR// 设置为聊天室消息
a.新建或者获取一个会话
[[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
//EMConversationTypeChat
//EMConversationTypeGroupChat
//EMConversationTypeChatRoom
聊天室会话
b.删除一个会话
[[EMClient sharedClient].chatManager deleteConversation:@"8001" deleteMessages:YES];
c.获取会话列表
EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
d.获取会话未读消息数
[EMConversation unreadMessagesCount];
a.发送消息
@brief 发送消息
@discussion
- (void)sendMessage:(EMMessage *)aMessage
progress:(void (^)(int progress))aProgressBlock
completion:(void (^)(EMMessage *message, EMError *error))aCompletionB
b.接受消息
//消息回调:EMChatManagerDelegate
//移除消息回调
[[EMClient sharedClient].chatManager removeDelegate:self];
//注册消息回调
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
@brief 接收到一条及以上非cmd消息
- (void)didReceiveMessages:(NSArray *)aM
c.解析普通消息
// 收到消息的回调,带有附件类型的消息可以用 SDK 提供的下载附件方法下载(后面会讲到)
- (void)didReceiveMessages:(NSArray *)aMessages
for (EMMessage *message in aMessages) {
EMMessageBody *msgBody = message.
switch (msgBody.type) {
case EMMessageBodyTypeText:
// 收到的文字消息
EMTextMessageBody *textBody = (EMTextMessageBody *)msgB
NSString *txt = textBody.
NSLog(@"收到的文字是 txt -- %@",txt);
case EMMessageBodyTypeImage:
// 得到一个图片消息body
EMImageMessageBody *body = ((EMImageMessageBody *)msgBody);
NSLog(@"大图remote路径 -- %@"
,body.remotePath);
NSLog(@"大图local路径 -- %@"
,body.localPath); // // 需要使用sdk提供的下载方法后才会存在
NSLog(@"大图的secret -- %@"
,body.secretKey);
NSLog(@"大图的W -- %f ,大图的H -- %f",body.size.width,body.size.height);
NSLog(@"大图的下载状态 -- %lu",body.downloadStatus);
// 缩略图sdk会自动下载
NSLog(@"小图remote路径 -- %@"
,body.thumbnailRemotePath);
NSLog(@"小图local路径 -- %@"
,body.thumbnailLocalPath);
NSLog(@"小图的secret -- %@"
,body.thumbnailSecretKey);
NSLog(@"小图的W -- %f ,大图的H -- %f",body.thumbnailSize.width,body.thumbnailSize.height);
NSLog(@"小图的下载状态 -- %lu",body.thumbnailDownloadStatus);
case EMMessageBodyTypeLocation:
EMLocationMessageBody *body = (EMLocationMessageBody *)msgB
NSLog(@"纬度-- %f",body.latitude);
NSLog(@"经度-- %f",body.longitude);
NSLog(@"地址-- %@",body.address);
case EMMessageBodyTypeVoice:
// 音频sdk会自动下载
EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgB
NSLog(@"音频remote路径 -- %@"
,body.remotePath);
NSLog(@"音频local路径 -- %@"
,body.localPath); // 需要使用sdk提供的下载方法后才会存在(音频会自动调用)
NSLog(@"音频的secret -- %@"
,body.secretKey);
NSLog(@"音频文件大小 -- %lld"
,body.fileLength);
NSLog(@"音频文件的下载状态 -- %lu"
,body.downloadStatus);
NSLog(@"音频的时间长度 -- %lu"
,body.duration);
case EMMessageBodyTypeVideo:
EMVideoMessageBody *body = (EMVideoMessageBody *)msgB
NSLog(@"视频remote路径 -- %@"
,body.remotePath);
NSLog(@"视频local路径 -- %@"
,body.localPath); // 需要使用sdk提供的下载方法后才会存在
NSLog(@"视频的secret -- %@"
,body.secretKey);
NSLog(@"视频文件大小 -- %lld"
,body.fileLength);
NSLog(@"视频文件的下载状态 -- %lu"
,body.downloadStatus);
NSLog(@"视频的时间长度 -- %lu"
,body.duration);
NSLog(@"视频的W -- %f ,视频的H -- %f", body.thumbnailSize.width, body.thumbnailSize.height);
// 缩略图sdk会自动下载
NSLog(@"缩略图的remote路径 -- %@"
,body.thumbnailRemotePath);
NSLog(@"缩略图的local路径 -- %@"
,body.thumbnailLocalPath);
NSLog(@"缩略图的secret -- %@"
,body.thumbnailSecretKey);
NSLog(@"缩略图的下载状态 -- %lu"
,body.thumbnailDownloadStatus);
case EMMessageBodyTypeFile:
EMFileMessageBody *body = (EMFileMessageBody *)msgB
NSLog(@"文件remote路径 -- %@"
,body.remotePath);
NSLog(@"文件local路径 -- %@"
,body.localPath); // 需要使用sdk提供的下载方法后才会存在
NSLog(@"文件的secret -- %@"
,body.secretKey);
NSLog(@"文件文件大小 -- %lld"
,body.fileLength);
NSLog(@"文件文件的下载状态 -- %lu"
,body.downloadStatus);
d.解析透传消息
- (void)didReceiveCmdMessages:(NSArray *)aCmdMessages{
for (EMMessage *message in aCmdMessages) {
EMCmdMessageBody *body = (EMCmdMessageBody *)message.
NSLog(@"收到的action是 -- %@",body.action);
e.消息已送达回执
@brief 接收到一条及以上已送达回执
- (void)didReceiveHasDeliveredAcks:(NSArray *)aM
f.消息已读回执
发送已读回执
// 发送已读回执。在这里写只是为了演示发送,在APP中具体在哪里发送需要开发者自己决定。
[[EMClient sharedClient].chatManager asyncSendReadAckForMessage:message];
接受已读回执
接收到一条及以上已读回执
@param aMessages
消息列表&EMMessage&
- (void)didReceiveHasReadAcks:(NSArray *)aM
以上方法基本都是在官方文档中可以找到,编写此文章,只为了方便大家随时可以打开简书,了解具体方法的使用,喜欢的请点个赞,谢谢!!
我是一名iOS开发程序猿,编程能让我找到自信,编程能让我找回自我.哈哈哈

我要回帖

更多关于 怎么关闭后应用程序 的文章

 

随机推荐