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 () <UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
 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<receive.length; i++) {
45         NSString *str1 = [NSString stringWithFormat:@"%C",[receive characterAtIndex:i]];
46         NSArray *keys = [deal.answers allKeys];
47         for (int j = 0; j<keys.count; j++) {
48             NSString *key = keys[j];
49             for (int k = 0; k< key.length; 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文件没有什么内容,仅是一些声明暂不提供!