热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

IOSQQ聊天界面的构建及自动回复功能的实现白衣→黑马

IOSQQ聊天界面的构建及自动回复功能的实现UITableView的功能非常之强大,在IOS程序开发中处于非常重要的地位。本文针对QQ聊天界面的构建及自动回复功能的实现进行介绍因本

IOS QQ聊天界面的构建及自动回复功能的实现


UITableView的功能非常之强大,在IOS程序开发中处于非常重要的地位。本文针对QQ聊天界面的构建及自动回复功能的实现进行介绍

因本人初学,代码有很多不足之处,还请各种批评指正!

效果演示:


功能说明:

1.通过plist文件加载本地的聊天数据

2.如果两条信息的时间相同则隐藏第二个的时间

3.键盘起落的监听

4.半智能自动回复

5.(很容易但未添加)滑动屏幕,隐藏键盘

代码思路

0.先创建两个类,一个用来保存显示的数据,一个用来保存数据的框架。

1.我们需要拿到plist中的聊天记录,将数据转换成模型,加载进内存。

2.在框架数据中添加BOOL类型属性,保存是否显示时间的数据。取出上一条数据的时间与当前数据的时间比较,如果相同则尺寸为0。

3.显示这些数据,我们需要在屏幕中添加UITableVIew,每一个cell用来显示数据,每个cell的高度都不相同,在框架数据类中添加保存cell高度的属性。

4.添加UITableView的数据源为控制器,实现数据源方法。

5.数据显示成功之后,再考虑键盘的处理,需要用到消息中心机制监听键盘的显示和隐藏,并执行相应的动作。

6.实现sent键的功能,这里需要拿到文本框的文本,然后进行上面的数据处理,可以创建一个类对这些操作进行封装。

7.消息可以发送之后,再考虑消息自动回复功能。

8.自动回复就是创建一个plist文件保存自动回复的内容,如果输入的信息中有对应的回复消息则返回对应回复信息,如果没有则返回默认回复内容。

9.plist文件中分别取输入的每个字和key中的每个字进行对比,判断返回内容。

代码实现:

1 //
2 // KWViewController.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "KWViewController.h"
10 #import "KWMessageModel.h"
11 #import "KWMessageDeal.h"
12 #import "KWFrameModel.h"
13 #import "KWCellView.h"
14
15 @interface KWViewController ()
16 @property (weak, nonatomic) IBOutlet UITableView *tableView;
17 @property (weak, nonatomic) IBOutlet UITextField *input;
18 @property (nonatomic,strong) NSMutableArray * messages;
19 @end
20
21 @implementation KWViewController
22 //懒加载
23 - (NSMutableArray *)messages{
24 if (!_messages) {
25 NSString * path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil];
26 NSArray *array = [NSArray arrayWithContentsOfFile:path];
27 NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:array.count];
28 for (NSDictionary *dict in array) {
29 KWFrameModel * last = [arrayM lastObject];
30 KWMessageModel *model = [KWMessageModel messageWithDict:dict];
31 KWFrameModel *frame = [[KWFrameModel alloc] init];
32 if ([last.model.time isEqualToString:model.time]) {
33 frame.timeshow = NO;
34 }else{
35 frame.timeshow = YES;
36 }
37 frame.model = model;
38 [arrayM addObject:frame];
39 }
40 _messages = [arrayM mutableCopy];
41 }
42 return _messages;
43 }
44 - (void)viewDidLoad{
45 [super viewDidLoad];
46 self.tableView.dataSource = self;
47 self.tableView.delegate = self;
48 self.input.delegate = self;
49 NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
50 [center addObserver:self selector:@selector(keyboardDidChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
51 }
52 # pragma mark 键盘处理
53 - (void)keyboardDidChange:(NSNotification *)notification{
54 // userInfo = {
55 // UIKeyboardAnimatiOnCurveUserInfoKey= 7;
56 // UIKeyboardAnimatiOnDurationUserInfoKey= "0.25";
57 // UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
58 // UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";
59 // UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";
60 // UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";
61 // UIKeyboardFrameChangedByUserInteraction = 0;
62 // UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
63 CGFloat keyboardY = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
64 CGFloat viewH = self.view.frame.size.height;
65 CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
66 [UIView animateKeyframesWithDuration:duration delay:0 options:7<<16 animations:^{
67 self.view.transform = CGAffineTransformMakeTranslation(0, keyboardY - viewH);
68 } completion:^(BOOL finished) {
69
70 }];
71 }
72 #pragma mark 数据源方法
73
74 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
75 return self.messages.count;
76 }
77
78 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
79 KWCellView *cell = [KWCellView cellViewWithTableView:tableView];
80 KWFrameModel *currentFrame = self.messages[indexPath.row];
81 cell.frameM = currentFrame;
82 return cell;
83 }
84
85 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
86 KWFrameModel * framem = self.messages[indexPath.row];
87 return framem.cellH;
88 }
89 # pragma mark 发送信息
90 - (void)sentMessage{
91 NSString *str = self.input.text;
92 KWMessageModel * sent = [KWMessageDeal messageDealWithContext:str type:0];
93 KWFrameModel *Fsent = [[KWFrameModel alloc] init];
94 //是否显示时间
95 KWFrameModel *last = self.messages.lastObject;
96
97 if ([last.model.time isEqualToString:sent.time]) {
98 Fsent.timeshow = NO;
99 }else{
100 Fsent.timeshow = YES;
101 }
102 Fsent.model = sent;
103 [self.messages addObject:Fsent];
104 }
105 # pragma mark textfield代理
106 - (BOOL)textFieldShouldReturn:(UITextField *)textField{
107 [self.view endEditing:YES];
108 [self sentMessage];
109 KWMessageModel *answer = [KWMessageDeal autoAnswer:self.input.text];
110 KWFrameModel *Fanswer = [[KWFrameModel alloc] init];
111 Fanswer.model = answer;
112 [self.messages addObject:Fanswer];
113 self.input.text = nil;
114 [self.tableView reloadData];
115 NSIndexPath * path = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
116 [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES];
117 return YES;
118 }
119
120 @end

KWViewController.m

1 //
2 // KWMessageModel.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "KWMessageModel.h"
10
11 @interface KWMessageModel ()
12 {
13 UIImage *_mimg;
14 UIImage *_micon;
15 }
16 @end
17 @implementation KWMessageModel
18 //生成图片
19 - (UIImage *)mimg{
20 if (_mimg) {
21 _mimg = [UIImage imageNamed:self.img];
22 }
23 return _mimg;
24 }
25
26
27 //工厂方法
28 - (instancetype)initWithDict:(NSDictionary *)dict{
29 if (self = [super init]) {
30 [self setValuesForKeysWithDictionary:dict];
31 }
32 return self;
33 }
34 + (instancetype)messageWithDict:(NSDictionary *)dict{
35 return [[self alloc] initWithDict:dict];
36 }
37 @end

KWMessageModel.m

1 //
2 // KWFrameModel.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "KWFrameModel.h"
10
11 @implementation KWFrameModel
12 - (void)setModel:(KWMessageModel *)model{
13 _model = model;
14 //屏幕尺寸
15 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
16 //计算时间框架
17 CGFloat timeX = 0;
18 CGFloat timeY = 0;
19 CGFloat timeW = screenWidth;
20 CGFloat timeH = kTimeH;
21 //计算时间是否隐藏
22 if (self.isTimeShow) {
23 self.timeF = CGRectMake(timeX, timeY, timeW, timeH);CGRectMake(0, 0, 0, 0);
24 }else{
25 self.timeF = CGRectMake(0, 0, 0, 0);
26 }
27 //计算图标框架
28 CGFloat icOnW= kIconW;
29 CGFloat icOnH= kIconH;
30 CGFloat iconX;
31 //判断消息类型
32 if (KWMessageTypeMe == self.model.type) {
33 icOnX= screenWidth - kMargin - kIconW;
34 }else{
35 icOnX= kMargin;
36 }
37 CGFloat icOnY= CGRectGetMaxY(self.timeF) + kMargin;
38 self.icOnF= CGRectMake(iconX, iconY, iconW, iconH);
39 //计算信息框架
40 CGSize textS = [self.model.text rectWithWidth:200 Heigth:MAXFLOAT FontSize:14];
41 CGFloat textW = textS.width + 2 * kTextEdgeInSets;
42 CGFloat textH = textS.height + 2 * kTextEdgeInSets;
43 CGFloat textX;
44 if (KWMessageTypeMe == self.model.type) {
45 textX = screenWidth - kMargin - iconW - textW;
46 }else{
47 textX = kMargin + iconW;
48 }
49 CGFloat textY = iconY;
50 self.textF = CGRectMake(textX, textY, textW, textH);
51 //行高
52 self.cellH = MAX(CGRectGetMaxY(self.iconF), CGRectGetMaxY(self.textF)) + kMargin;
53 }
54 /**
55 * 重新描述
56 */
57 - (NSString *)description{
58 NSString *str = [NSString stringWithFormat:@"time%@-icon%@-text%@",NSStringFromCGRect(self.timeF),NSStringFromCGRect(self.iconF),NSStringFromCGRect(self.textF)];
59 return str;
60 }
61 @end

KWFrameModel.m

1 //
2 // KWMessageDeal.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "KWMessageDeal.h"
10
11 @interface KWMessageDeal ()
12 {
13 NSString *_time;
14 }
15
16 @end
17
18 @implementation KWMessageDeal
19 + (KWMessageModel *)messageDealWithContext:(NSString *)context type:(KWMessageType)type{
20 KWMessageDeal *deal = [[KWMessageDeal alloc] init];
21 KWMessageModel *model = [[KWMessageModel alloc] init];
22 model.text = context;
23 model.type = type;
24 model.time = deal.time;
25 return model;
26 }
27 - (NSString *)time{
28 NSDate *date = [[NSDate alloc] init];
29 NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
30 formatter.dateFormat = @"HH:mm";
31 NSString *time = [formatter stringFromDate:date];
32 return time;
33 }
34 - (NSDictionary *)answers{
35 if (!_answers) {
36 NSString *path = [[NSBundle mainBundle] pathForResource:@"answer.plist" ofType:nil];
37 _answers = [NSDictionary dictionaryWithContentsOfFile:path];
38 }
39 return _answers;
40 }
41 + (KWMessageModel *)autoAnswer:(NSString *)receive{
42 KWMessageDeal *deal = [[KWMessageDeal alloc] init];
43 NSString *answer = nil;
44 for (int i =0; i) {
45 NSString *str1 = [NSString stringWithFormat:@"%C",[receive characterAtIndex:i]];
46 NSArray *keys = [deal.answers allKeys];
47 for (int j = 0; j) {
48 NSString *key = keys[j];
49 for (int k = 0; k) {
50 NSString *str2 = [NSString stringWithFormat:@"%C",[key characterAtIndex:k]];
51 if ([str1 isEqualToString:str2]) {
52 answer = deal.answers[key];
53 return [self messageDealWithContext:answer type:1];
54 }
55 }
56 }
57 }
58 answer = @"我看不懂啊!";
59 return [self messageDealWithContext:answer type:1];
60 }
61 @end

KWMessageDeal.m

1 //
2 // NSString+my.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "NSString+my.h"
10
11 @implementation NSString (my)
12 - (CGSize)rectWithWidth:(CGFloat)width Heigth:(CGFloat)height FontSize:(int)fontSize {
13 NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]};
14 CGRect rect = [self boundingRectWithSize:CGSizeMake(width, height) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
15 return rect.size;
16 }
17 @end

NSString+my.m

1 //
2 // UIImage+my.m
3 // 19-扣扣聊天(优化)
4 //
5 // Created by kevin on 14-6-1.
6 // Copyright (c) 2014年 heima. All rights reserved.
7 //
8
9 #import "UIImage+my.h"
10
11 @implementation UIImage (my)
12 + (UIImage *)imageResize:(UIEdgeInsets)edgeInsets Named:(NSString *)name{
13 UIImage *img = [UIImage imageNamed:name];
14 return [img resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
15 }
16 @end

UIImage+my.m

对应的.h文件没有什么内容,仅是一些声明暂不提供!

 

发表于

2014-06-03 00:42 

白衣→黑马 

阅读(722

评论(0

编辑 

收藏 

举报

 



推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
author-avatar
mobiledu2502927267
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有