Habber - IOS XMPP 客户端 教程 (续)对方输入状态显示
来源:互联网 发布:淘宝助理设置快递模板 编辑:程序博客网 时间:2024/05/23 12:07
Train of thought
要显示对方输入状态,也就是说要给对方发送一个标志,对方接收到这个标志,就知道你正在输入,然后在标题栏上显示你正在输入就行了。
那怎么发送标志呢?知道了我们传输的信息都是XML文件,也就是要接收两个不同的状态。增加一个标记composing,假如我们输入的时候它就传递isTyping,不输入的时候什么都不传就好了。
Do it!
OK, 有了思路我们就着手去做。
首先我得知道我们什么时候正在输入什么时候停止输入,而且我们知道输入框是一个UITextView,由于真正的控件调用都是框架做好了的,我们要进入框架。
找到UUInputFunctionView.h,好啊,我们看到了定义成UITextView的*TextViewInput这个小东西,接着进入m文件中去!
在m文件中我们发现TextViewDelegate已经接收了代理,
- (void)textViewDidBeginEditing:(UITextView *)textView
和- (void)textViewDidEndEditing:(UITextView *)textView
,我们需要的正是他们!太好了找到了能够发现输入状态变更的方法,我们就该让它们为我们提供服务了!
改框架:UUInputFunctionView.h中@Protocol中我们增加两个方法- (void)composing;
和- (void)endComposing;
,添加好后我们就要把钥匙交给代理了。交接,UUInputFunctionView.m中
- (void)textViewDidBeginEditing:(UITextView *)textView
{
placeHold.hidden = self.TextViewInput.text.length > 0;
[self.delegate composing];
}
和- (void)textViewDidEndEditing:(UITextView *)textView
{
placeHold.hidden = self.TextViewInput.text.length > 0;
[self.delegate endComposing];
}实现代理:回到我们UUChatViewController.m中,增加两个方法:
- (void)composing {}
和- (void)endComposing {}
,方法内容先留空,接下来我们要大改了。首先,改变发送XML的结构:
#pragma mark - 发送XML封装数据- (void)sendXML:(NSString *)message image:(UIImage *)img voice:(NSData *)voice time:(NSUInteger)second isComposing:(NSString *)status{ //生成xml //<composing> NSXMLElement *composing = [NSXMLElement elementWithName:@"composing"]; [composing setStringValue:status]; //<body> NSXMLElement *body = [NSXMLElement elementWithName:@"body"]; [body setStringValue:message]; //<message> NSXMLElement *mes = [NSXMLElement elementWithName:@"message"]; //<message type = chat> [mes addAttributeWithName:@"type" stringValue:@"chat"]; //<message type = "chat" to = _chatUserName> [mes addAttributeWithName:@"to" stringValue:_chatUserName]; //<message type = "chat" to = _chatUserName from = ...> [mes addAttributeWithName:@"from" stringValue:[[NSUserDefaults standardUserDefaults] stringForKey:USERID]]; //<message ...><composing></composing><body></body></message> [mes addChild:composing]; [mes addChild:body]; if (img) { NSData *imgData = UIImageJPEGRepresentation(img, 0.1); NSString *imgStr=[imgData base64EncodedStringWithOptions:0]; //<message ...><body></body><img></img></message> NSXMLElement *imgAttachment = [NSXMLElement elementWithName:@"image"]; [imgAttachment setStringValue:imgStr]; [mes addChild:imgAttachment]; } if (voice) { NSString *voiceStr = [voice base64EncodedStringWithOptions:0]; NSXMLElement *voiceAttachment = [NSXMLElement elementWithName:@"voice"]; [voiceAttachment setStringValue:voiceStr]; [voiceAttachment addAttributeWithName:@"voiceTime" unsignedIntegerValue:second]; [mes addChild:voiceAttachment]; } //发送消息 [[self xmppStream] sendElement:mes]; NSLog(@"%@", mes);}
发送结构改好了,我们就可以填充实现代理的方法了:
- (void)composing { [self sendXML:@"" image:nil voice:nil time:0 isComposing:@"isTyping"];}- (void)endComposing { [self sendXML:@"" image:nil voice:nil time:0 isComposing:@""];}
我们还要更改接受的配置:
//收到消息后把消息传递给代理- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { //解析xml NSString *composing = [[message elementForName:@"composing"] stringValue]; composing = !composing ? @"" : composing; NSString *msg = [[message elementForName:@"body"] stringValue]; msg = !msg ? @"" : msg; NSString *img = [[message elementForName:@"image"] stringValue]; img = !img ? @"" : img; NSString *voice = [[message elementForName:@"voice"] stringValue]; NSString *voiceTime = [[[message elementForName:@"voice"] attributeForName:@"voiceTime"] stringValue]; if (!voice) { voice = @""; voiceTime = @""; } NSString *from = [[message attributeForName:@"from"] stringValue]; NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:composing forKey:@"composing"]; [dict setObject:msg forKey:@"msg"]; [dict setObject:img forKey:@"photo"]; [dict setObject:voice forKey:@"voice"]; [dict setObject:voiceTime forKey:@"voiceTime"]; [dict setObject:from forKey:@"sender"]; [_messageDelegate newMessageReceived:dict];}
这样我们能够接收到输入状态了,我们还需要对接收过来的数据进行处理:
- (void)newMessageReceived:(NSDictionary *)messageContent { dispatch_async(dispatch_get_main_queue(), ^{ NSDictionary *dic = [NSDictionary dictionary]; NSString *composing = [messageContent objectForKey:@"composing"]; NSString *msg = [messageContent objectForKey:@"msg"]; NSString *imageStr = [messageContent objectForKey:@"photo"]; NSString *voiceStr = [messageContent objectForKey:@"voice"]; NSString *voiceTimeStr = [messageContent objectForKey:@"voiceTime"]; NSString *from = [messageContent objectForKey:@"sender"]; if (imageStr.length > 0) { NSData *imgData = [[NSData alloc] initWithBase64EncodedString:imageStr options:0]; UIImage *image = [UIImage imageWithData:imgData]; dic = @{@"picture": image, @"type": @(UUMessageTypePicture), @"sender": from}; } else if (voiceStr.length > 0) { NSData *voiceData = [[NSData alloc] initWithBase64EncodedString:voiceStr options:0]; dic = @{@"voice": voiceData, @"strVoiceTime": voiceTimeStr, @"type": @(UUMessageTypeVoice), @"sender": from}; } else { dic = @{@"strContent": msg, @"type": @(UUMessageTypeText), @"sender": from}; } if (![composing isEqualToString:@"isTyping"]) { [self dealTheFunctionData:dic]; self.navigationItem.title = _chatUserName; } else { self.navigationItem.title = @"Is typing..."; } });}
这里需要注意,如果我们接收过来的是 文本,图片还有音频都为空,只有标志为”isTyping”的文本,为了防治cell显示接收到的空字符,我们还要加以过滤:
- (void)dealTheFunctionData:(NSDictionary *)dic{ if (![[dic objectForKey:@"strContent"] isEqualToString:@""]) { [self.chatModel addSpecifiedItem:dic]; [self.chatTableView reloadData]; [self tableViewScrollToBottom]; }}
好了,现在我们能够在聊天窗口显示“Is typing…”的状态了,但是我们还需要在“好友列表”中加一层过滤,不然只要接收到信息它就会显示一条未读信息,对方只是改变输入状态它都会显示一条未读信息,这样是不行的,来到“FriendListTableViewController.m”中,我们要改变其接收和显示的规则:
- (void)newMessageReceived:(NSDictionary *)messageContent { NSDictionary *dic = [NSDictionary dictionary]; NSString *composing = [messageContent objectForKey:@"composing"]; NSString *msg = [messageContent objectForKey:@"msg"]; NSString *imageStr = [messageContent objectForKey:@"photo"]; NSString *voiceStr = [messageContent objectForKey:@"voice"]; NSString *voiceTimeStr = [messageContent objectForKey:@"voiceTime"]; NSString *from = [messageContent objectForKey:@"sender"]; if (imageStr.length > 0) { NSData *imgData = [[NSData alloc] initWithBase64EncodedString:imageStr options:0]; UIImage *image = [UIImage imageWithData:imgData]; dic = @{@"picture": image, @"type": @(UUMessageTypePicture), @"sender": from}; } else if (voiceStr.length > 0) { NSData *voiceData = [[NSData alloc] initWithBase64EncodedString:voiceStr options:0]; dic = @{@"voice": voiceData, @"strVoiceTime": voiceTimeStr, @"type": @(UUMessageTypeVoice), @"sender": from}; } else { dic = @{@"strContent": msg, @"type": @(UUMessageTypeText), @"sender": from}; } //重点来了~ if ((![composing isEqualToString:@"isTyping"] && ![msg isEqualToString:@""]) || ![imageStr isEqualToString:@""] || ![voiceStr isEqualToString:@""]) { //收到消息数组 [_messages addObject:dic]; //每次刷新表格,就可以看到有多少条未读信息 [self.tableView reloadData]; }}
OK!我们改变了它的规则,只要是”isTyping”都会被过滤掉!
好了,对方输入状态的显示的功能有了,改了我两个多小时,博客居然写了快一个小时!It’s wired…but, whatever.
改起来有些繁琐,但也算是对之前发送接收消息一个小的应用,不难理解,注意一些过滤规则就是了。
- Habber - IOS XMPP 客户端 教程 (续)对方输入状态显示
- Habber - IOS XMPP 客户端 教程 (一)准备工作
- Habber - IOS XMPP 客户端 教程 (三)VC始于LoginViewController、、
- Habber - IOS XMPP 客户端 教程 (四)聊天界面制作
- Habber - IOS XMPP 客户端 教程 (终)总结与反思
- Habber - IOS XMPP 客户端 教程 (二)应用XMPP&代理&全局变量
- Habber - IOS XMPP 客户端 教程 (零)简介与源码下载
- Habber - IOS XMPP 客户端 教程 (三)着手制作好友列表
- IOS使用XMPP最新教程(三)获取好友列表 (通过获取好友状态)
- XMPP iOS客户端开发(二) 通信
- XMPP iOS客户端 添加好友 (3)
- XMPP IOS客户端一
- xmpp ios客户端二
- xmpp iOS 客户端三
- IOS XMPP 聊天客户端
- xmpp iOS 聊天客户端
- xmpp iOS 聊天客户端
- 【iOS XMPP】使用XMPPFramewok(三):好友状态
- Linux必学的60个命令
- Android:Asynctask简单使用
- actionSheet和从相册选取图片
- nodejs的N个tip
- STL之remove算法详解
- Habber - IOS XMPP 客户端 教程 (续)对方输入状态显示
- CentOS系统中安装chrome浏览器
- golang 动态 实例化 结构体
- FCoE,DCB
- C# 读取ini配置文件
- Java访问修饰符
- C#随机验证码
- 天地图导入AndroidStuido中
- iOS面试题9