效果展示:
01 加载模型数据\创建cell
在这里面, 这个代码和步骤, 与我们上一次总结的一样, 唯一要注意的细节就是我们在
昨天创建自定义cell
的第二步中的有一个创建cell
中的控件, 中
我们创建:
/**
* 时间
*/
@property (nonatomic, weak) UILabel *timeView;
/**
* 头像
*/
@property (nonatomic, weak) UIImageView *iconView;
/**
* 正文
*/
@property (nonatomic, weak) UIButton *textView;
这几个控件的时候, 我们会发现, 他们都是弱指针, 所以我们不能直接将这些控件添加给我们的cell
,所以我们一般会选择这样做:
// 1.时间
UILabel *timeView = [[UILabel alloc] init];
[self.contentView addSubview:timeView];
self.timeView = timeView;
// 2.头像
UIImageView *iconView = [[UIImageView alloc] init];
[self.contentView addSubview:iconView];
self.iconView = iconView;
// 3.正文
UIButton *textView = [[UIButton alloc] init];
[self.contentView addSubview:textView];
self.textView = textView;
为什么不可以直接添加到cell
中???
由于 , 这个是利用弱指针创建的, 所以, 当我们这一行添加代码运行过之后, 这些控件会自被销毁
02 计算子控件的frame
我们在计算我们的frame的时候, 情况和我上一次做的微博一样
frame的.h文件
// 正文的字体
#define GJTextFont [UIFont systemFontOfSize:15]
#import <Foundation/Foundation.h>
@class GJMessage;
@interface GJMessageFrame : NSObject
/**
* 头像的frame
*/
@property (nonatomic, assign, readonly) CGRect iconF;
/**
* 时间的frame
*/
@property (nonatomic, assign, readonly) CGRect timeF;
/**
* 正文的frame
*/
@property (nonatomic, assign, readonly) CGRect textF;
/**
* cell的高度
*/
@property (nonatomic, assign, readonly) CGFloat cellHeight;
/**
* 数据模型
*/
@property (nonatomic, strong) GJMessage *message;
@end
frame的.m文件
#import "GJMessageFrame.h"
#import "GJMessage.h"
@implementation GJMessageFrame
/**
* 计算文字尺寸
*
* @param text 需要计算尺寸的文字
* @param font 文字的字体
* @param maxSize 文字的最大尺寸
*/
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *attrs = @{NSFontAttributeName : font};
return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}
- (void)setMessage:(GJMessage *)message
{
_message = message;
// 间距
CGFloat padding = 10;
// 屏幕的宽度
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
// 1.时间
CGFloat timeX = 0;
CGFloat timeY = 0;
CGFloat timeW = screenW;
CGFloat timeH = 40;
_timeF = CGRectMake(timeX, timeY, timeW, timeH);
// 2.头像
CGFloat iconY = CGRectGetMaxY(_timeF);
CGFloat iconW = 40;
CGFloat iconH = 40;
CGFloat iconX;
if (message.type == GJMessageTypeOther) {// 别人发的
iconX = padding;
} else { // 自己的发的
iconX = screenW - padding - iconW;
}
_iconF = CGRectMake(iconX, iconY, iconW, iconH);
// 3.正文
CGFloat textY = iconY;
// 文字的尺寸
CGSize textMaxSize = CGSizeMake(150, MAXFLOAT);
CGSize textSize = [self sizeWithText:message.text font:MJTextFont maxSize:textMaxSize];
CGFloat textX;
if (message.type == GJMessageTypeOther) {// 别人发的
textX = CGRectGetMaxX(_iconF) + padding;
} else {// 自己的发的
textX = iconX - padding - textSize.width;
}
// _textF = CGRectMake(textX, textY, textSize.width, textSize.height);
_textF = (CGRect){{textX, textY}, textSize};
// 4.cell的高度
CGFloat textMaxY = CGRectGetMaxY(_textF);
CGFloat iconMaxY = CGRectGetMaxY(_iconF);
_cellHeight = MAX(textMaxY, iconMaxY) + padding;
}
@end
03 修正聊天细节
小细节:
1. 我们如果按照上面的代码写的话, 就会发现, 我们的每一个聊天内容(cell
)就可以被选中. 在我们的[super viewDidLoad];
下面写上这样一行代码就可以了: (这个是利用代码写的)
self.tableView.allowSelection = NO;
在storyboard
中也可以这个大家可以自己找一下, 就是在我们的tableView
中的
2 . 有些消息时间一致, 但是它依旧会显示两个相同的时间, 解决问题:
- 首先, 我们如果确定两个相同的时间不会一起显示, 我们就需要将第二个相同的时间隐藏 所以我们就需要在我们的数据模型类中增加一个新的属性
hiddenTime
他的类型是BOOL
是为了判断是否显示时间 代码就是:
数据模型类.h文件
@property (nonatomic, assign) BOOL hiddenTime;
frame模型类.m文件
if (massage.hiddenTime == NO){
CGFloat timeX = 0;
CGFloat timeY = 0;
CGFloat timeW = screenW;
CGFloat timeH = 40;
_timeF = CGRectMake(timeX, timeY, timeW, timeH);
}
- 如何确定这个BOOL类型的正确性???
我们就需要在我们的控制器的数据转模型中写了
为了比较时间相同与否, 我们需要拿到上一个时间, 然后两个时间进行比较, 这就需要在控制器中的数据转模型中写了, 代码如下:
for (NSDictionary *dict in dictArray) {
// 消息模型
GJMessage *msg = [GJMessage messageWithDict:dict];
// 取出上一个模型
GJMessageFrame *lastMf = [mfArray lastObject];
GJMessage *lastMsg = lastMf.message;
// 判断两个消息的时间是否一致
msg.hideTime = [msg.time isEqualToString:lastMsg.time];
// frame模型
GJMessageFrame *mf = [[GJMessageFrame alloc] init];
mf.message = msg;
// 添加模型
[mfArray addObject:mf];
}
为什么是lastObject
???
这是由于我们在添加模型的之前, 我们最后一个模型就是就是我们的上一个时间. 所以, 我们使用的是lastObject
而且, 整个代码要写在[mfArray addObject:mf];
3 . 关于我们聊天正文的背景图片
我们在设置聊天正文背景的时候, 是不是直接将图片放到正文后面???
其实不是的, 如果我们是直接拖到里面会发生这样的情况:
我们可以看到, 我们的那个图片已经变形了, 所以我们解决的办法就是利用我们美工制作的图片的原理:
其实我们可以发现, 在我们的正文背景图片中, 边缘的都有点失真了,
而中间的那一部分, 却很完美,(这个就是我们美工利用特殊的工具才能做出来的效果) 所以我们要利用一个方法, 当文字, 变多时, 将我们的图片中间的那个一部分不断的放大, 不断地填充. 来完成我们平时QQ聊天时的那种效果.
而, 我们要不断放大我们图片中间的那一点. 就系统, 需要告诉我们的系统, 是需要将哪一个部分不断放大, 这就需要下面的这个方法了 :
当然这是在我们的GJMassageCell.m
文件中写的
// 正文的背景
if (message.type == MJMessageTypeMe) { // 自己发的,蓝色
UIImage *normal = [@"chat_send_nor"];
CGFloat w = normal.size.width * 0.5;
CGFloat h = normal.size.height * 0.5;
UIImage *lastNomal = [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)];
[self.textView setBackgroundImage: lastNormal forState: UIControlStateNormal];
} else { // 别人发的,白色
// 大概的步骤和上面一样
}
`
注意: 我们关于那个一个中间部分的算法, 其实就是最中心的那一个点, 只是这一个点, 坐标连1都不到.
当然这样, 我们的代码可以封装(以前我们就说过, 一旦遇到相同的代码, 一般都可以封装)
4 .封装上面的部分代码:
为什么封装代码???
有时候 , 在做其他的项目的时候 , 发现有时候, 我们的这种图片拉伸, 和上面的文本框大小设置, 有很多的地方可以使用, 但是如果我们不进行封装的话 ,一旦我们在其他地方使用的时候, 就必须拥有这个模型.
解决方法 ,就是创建一个分类, 来存储我们的这些将来可以共用的方法, 而, 我们注意到, 我们的上面的图片拉伸,是我们的UIImage
的, 所以我们要创建一个UIImage
的分类来 存放这个拉伸图片的方法.
首先创建一个UIImage
的分类:
然后在这个分类中写我们的方法:
// .h文件
#import <UIKit/UIKit.h>
@interface UIImage (Extension)
+ (UIImage *)resizableImage:(NSString *)name;
@end
图片分类的.m文件
#import "UIImage+Extension.h"
@implementation UIImage (Extension)
/**
* 返回一张可以随意拉伸不变形的图片
*
* @param name 图片名字
*/
+ (UIImage *)resizableImage:(NSString *)name
{
UIImage *normal = [UIImage imageNamed:name];
CGFloat w = normal.size.width * 0.5;
CGFloat h = normal.size.height * 0.5;
return [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)];
}
@end
而这个方法的调用, 就变成这个样子了:
// 4.正文的背景
if (message.type == GJMessageTypeMe) { // 自己发的,蓝色
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];
} else { // 别人发的,白色
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_recive_nor"] forState:UIControlStateNormal];
}
而我们先前说的, 关于我们正文字体的设置, 也是相同的道理. 但是区别就在于, 我们字体设置, 是创建一个对象方法, 而上面的是类方法
// .h文件
#import <Foundation/Foundation.h>
@interface NSString (Extension)
/**
* 返回字符串所占用的尺寸
*
* @param font 字体
* @param maxSize 最大尺寸
*/
- (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize;
@end
// .m文件
#import "NSString+Extension.h"
@implementation NSString (Extension)
- (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *attrs = @{NSFontAttributeName : font};
return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}
调用的方式为:
[textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.contentView addSubview:textView];
self.textView = textView;
新知识: (这一部分的代码和我们做的这个应用的代码不相关)
4. 通知机制:
**原因: **
在上面我们会发现, 当我们的点击那个输入按钮的时候, 我们的键盘(手机键盘)弹出, 会将我们输入的那个按钮遮住, 所以我们要利用一个新的知识让我们的输入框, 当我们的键盘弹出的时候, 他会逐渐上升, 当键盘隐藏的时候, 他会逐渐下降.
为什么不使用代理
因为, 如果是监听我们键盘的弹出或者隐藏, 是没有办法用代理的, 所以我们要学习新的知识: 通知
4.1 什么是通知:
通知就是用于多个对象之间通信的.
假如说对象A发生了一些事情, 他想告诉对象B, 和对象C, 甚至对象D都可以.
**代理和通知之间的区别: **
代理只能是一对一, 就是一个对象对应一个对象 .
通知可以是一对多, 多对一, 多对多
而今天我们讲通知那些知识:
- 通知的发布
- 通知的监听
- 通知的移除
4. 2 通知的三要素:
- 通知名称
- 通知发布者
- 通知接受者
4. 3 通知中心
从上面的图片我们也可以看出, 我们通知的发布者, 和接收者 , 中间需要一个通知中心帮助我们把通知发布者, 发布的通知告诉接收者.
4. 4发布通知:
以上的三个方法都是我们发布通知的方法.
4. 5 注册通知监听器
4. 6 取消注册通知监听器
其实为了避免出现野指针, 我们一般会在监听器销毁之前取消注册, 因为, 就像上面所说的, 如果不这样做的话, 会导致系统崩溃
话不多说, 直接看代码:
**介绍: **
这是一个利用, 用户阅读新闻的情景介绍通知的, 所以在这里面有两个类:
一个是company
新闻公司.
一个是person
用户类 .
公司通过用户所喜爱的栏目(军事新闻, 或者娱乐新闻)来决定是否给用户发送通知
代码如下:
首先是公司类中的代码
#import <Foundation/Foundation.h>
@interface NewsCompany : NSObject
/**
* 机构名称
*/
@property (nonatomic, copy) NSString *name;
@end
就是一个简单的新闻公司名称属性
person类(.h文件的代码就不写了, 因为就只是一个简单的方法声明, 这个方法的名称可以在.m文件中看到)
#import "Person.h"
#import "NewsCompany.h"
@implementation Person
- (void)newsCome:(NSNotification *)note
{
// 通知的发布者
NewsCompany *obj = note.object;
NSLog(@"%@接收到了%@发出的通知,通知内容是:%@", self.name, obj.name, note.userInfo);
}
- (void)dealloc
{
// [super dealloc];
// 取消注册通知监听器
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
main函数:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "NewsCompany.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// 1.初始化机构
NewsCompany *tx = [[NewsCompany alloc] init];
tx.name = @"腾讯新闻";
NewsCompany *sina = [[NewsCompany alloc] init];
sina.name = @"新浪新闻";
// 2.初始化3个人
Person *zhangsan = [[Person alloc] init];
zhangsan.name = @"张三";
Person *lisi = [[Person alloc] init];
lisi.name = @"李四";
Person *wangwu = [[Person alloc] init];
wangwu.name = @"王五";
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// 3.添加监听器
// zhangsan只监听tx发出的junshi_news_come通知
// 2
[center addObserver:zhangsan selector:@selector(newsCome:) name:@"junshi_news_come" object:nil];
[center addObserver:zhangsan selector:@selector(newsCome:) name:@"yule_news_come" object:nil];
// 1
[center addObserver:lisi selector:@selector(newsCome:) name:nil object:tx];
// 2
[center addObserver:wangwu selector:@selector(newsCome:) name:nil object:nil];
// 4.发布新闻
// tx发布了一则叫做junshi_news_come的通知
[center postNotificationName:@"junshi_news_come"
object:tx
userInfo:@{@"title" : @"伊拉克战争停止了",
@"intro" : @"伊拉克战争停止了.........."}];
// sina发布了一则叫做junshi_news_come的通知
[center postNotificationName:@"yule_news_come"
object:sina
userInfo:@{@"title" : @"6456456456456",
@"intro" : @"7657567567567"}];
}
return 0;
}
这个代码就可以简单的介绍了, 关于通知的一些方法的使用.
说了这么多的通知, 他和我们的键盘有什么关系吗???
其实, 我们说了这么就是想讲一下, 我们的这个东西:
我们的这个UIDevice
中的一些通知, 相当一部分是用户不需要关心的, 因为 , 但是, 作为我们开发者, 我们必须知道, 这些通知, 其中就包括了, 我们的键盘通知 :
而上面的关于我们键盘的通知, 那些又是对现在的我们来说是有用的呢???
其实我们需要在意的是那些, 带Will
的方法, 因为我们的输入框是要随着我们键盘的上升而上升, 随着我们键盘的下降而下降的.
回到正题上: 利用上面的知识完成程序
5. 键盘处理
首先, 由于我们通知是控制器监听我们键盘的弹出与显示
所以我们, 这个键盘处理的代码应该写在控制器里面
首先我们是要在viewDidLoad
这个方法中写: 其次, 按照上面的介绍方法
- 首先, 应该监听键盘的通知
// 2.监听键盘的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
2 . 然后我们要在监听键盘frame变化的方法中写我们的代码:
/**
* 当键盘改变了frame(位置和尺寸)的时候调用
*/
- (void)keyboardWillChangeFrame:(NSNotification *)note
{
// 设置窗口的颜色
self.view.window.backgroundColor = self.tableView.backgroundColor;
// 0.取出键盘动画的时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 1.取得键盘最后的frame
CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 2.计算控制器的view需要平移的距离
CGFloat transformY = keyboardFrame.origin.y - self.view.frame.size.height;
// 3.执行动画
[UIView animateWithDuration:duration animations:^{
self.view.transform = CGAffineTransformMakeTranslation(0, transformY);
}];
}
/*
UIKeyboardAnimationCurveUserInfoKey = 7; // 动画的执行节奏(速度)
UIKeyboardAnimationDurationUserInfoKey = "0.25"; // 键盘弹出\隐藏动画所需要的时间
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";
UIKeyboardFrameChangedByUserInteraction = 0;
// 键盘弹出
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";// 键盘刚出来那一刻的frame
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; // 键盘显示完毕后的frame
// 键盘隐藏
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";
*/
这里面的设置窗口颜色的那一行代码的意思, 就是:
当我们的键盘退出的那一刻, 我们会发现, 在键盘和我们tableView之间会出现黑色区域, 这是由于: 其实在我们手机界面后面还有一个winview, 为了不让颜色显示出来所以要改变颜色
注意这一行代码为什么是这样写:
// 1.取得键盘最后的frame
CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 2.计算控制器的view需要平移的距离
CGFloat transformY = keyboardFrame.origin.y - self.view.frame.size.height;
// 3.执行动画
[UIView animateWithDuration:duration animations:^{
self.view.transform = CGAffineTransformMakeTranslation(0, transformY);
}];
- 首先, 拿到我们键盘最后的frame
- 然后再利用键盘的Y值 - view的高度
- 这个差值就是view移动的距离
为什么是这样算的???
分析一下:
假设view的高度为480
当我们的键盘的Y值为264的时候, 那么算出来的值就是 -216(这个距离恰好是键盘隐藏时的距离)
如果键盘的Y值为480(即为隐藏状态)-480 = 0, 那么view就是充满整个屏幕.
- 取消注册监听通知
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- 后面小处理
用过QQ都知道, 当我们拖拽我们手机上面的界面时 , 我们的键盘会自动隐藏 , 所以我们现在做好这个工作
要想让键盘由于用户的拖拽 自动隐藏, 我们需要监听用户的点击, 拖拽, 那就需要利用代理
由于我们以前就介绍过scrollView, 所以我们就需要用scrollView的代理, 当然, 我们的UITableViewDelegate继承自scrollView的代理, 所以我们只用直接遵守UITableView的协议, 就好了. 然后在代理中写上隐藏键盘的代码:
/**
* 当开始拖拽表格的时候就会调用
*/
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 退出键盘
[self.view endEditing:YES];
}
@end
06. 文本输入框处理
一些小的处理;
第一个是显示我们的发送按钮, 以前的是return 现在我们给改成了send
第二个的那个Auto-enable-Return Key, 当我们在文本框内输入数据的时候, 就文本框没有数据, 那个发送按钮依旧可以点击, 而当我们选择这个选项之后, 就可以解决这个问题
第三个: 注意到, 我们的在文本框输入数据的时候, 发现: 数据是直接顶格显示的, 这个不够美观, 所以我们要将文本框的左边留一点空隙
- 首先, 利用拖线 让文本框成为控制器的属性, (
inputView
) - 其实我们每一个文本框都有这两个view (
leftView
,rightView
)我们选择就是用一个看不见的leftView来使文本框左边留出一点缝隙
// 3.设置文本框左边显示的view
self.inputView.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
- 然后, 我们的每一个view都具有这样一个枚举:
leftViewMode
他是用来分出这个leftView显示的方式, 时间
self.inputView.leftViewMode = UITextFieldViewModeAlways;
而这个就是永远显示的意思
07 自动回复
在我们的自动回复之前, 首先我们要完成的是, 我们可以发消息
如果要使我们发送的消息可以显示到界面上, 我们首先要监听文本框和键盘的点击.
- 遵守代理:
UITextFieldDelegate
- 实现方法:
/**
* 点击了return按钮(键盘最右下角的按钮)就会调用
*/
- (BOOL)textFieldShouldReturn:(UITextField *)textField
然后在这个方法中写关于我们发送消息的代码:
首先, 我们可以试想一下, 关于自动回复, 意思就是我们发一条消息, 他就自动回复一条 , 我们是如果发的(就是简单的增加一个模型, 在模型中添加数据), 它就会如何会h回复, 所以我们直接将我们发送消息, 和系统自动回复消息, 整合到一个方法中去. 只需要告诉(传参)这个方法, 是谁发消息以及发送消息的内容:
/**
* 发送一条消息
*/
- (void)addMessage:(NSString *)text type:(GJMessageType)type
{
// 1.数据模型
GJMessage *msg = [[GJMessage alloc] init];
msg.type = type;
msg.text = text;
// 设置数据模型的时间
NSDate *now = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"HH:mm";
msg.time = [fmt stringFromDate:now];
// 看是否需要隐藏时间
GJMessageFrame *lastMf = [self.messageFrames lastObject];
GJMessage *lastMsg = lastMf.message;
msg.hideTime = [msg.time isEqualToString:lastMsg.time];
// 2.frame模型
GJMessageFrame *mf = [[GJMessageFrame alloc] init];
mf.message = msg;
[self.messageFrames addObject:mf];
// 3.刷新表格
[self.tableView reloadData];
// 4.自动滚动表格到最后一行
NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
而发送消息的步骤就在上面的方法中
而这样我们的文本框代理需要做的就是调用该方法然后
将是谁发的, 以及发送的内容告诉这个方法便可:
#pragma mark - 文本框代理
/**
* 点击了return按钮(键盘最右下角的按钮)就会调用
*/
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// 1.自己发一条消息
[self addMessage:textField.text type:MJMessageTypeMe];
// 2.自动回复一条消息
NSString *reply = [self replayWithText:textField.text];
[self addMessage:reply type:MJMessageTypeOther];
// 3.清空文字
self.inputView.text = nil;
// 返回YES即可
return YES;
}
至于自动回复, 我们写了一个这样的plist文件:
只要我们遍历我们发送的内容中的每一个汉字, 有和上面相同的汉字, 就自动回复后面的文字, 如果没有就直接发送滚蛋
**取出plist文件: **
- (NSDictionary *)autoreply
{
if (_autoreply == nil) {
_autoreply = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"autoreply.plist" ofType:nil]];
}
return _autoreply;
}
遍历
/**
* 根据自己发的内容取得自动回复的内容
*
* @param text 自己发的内容
*/
- (NSString *)replayWithText:(NSString *)text
{
for (int i = 0; i<text.length; i++) {
NSString *word = [text substringWithRange:NSMakeRange(i, 1)];
if (self.autoreply[word]) return self.autoreply[word];
}
return @"滚蛋";
}
这样就完成了, 自动回复功能了.
作者说:
以后的代码量可能比较多, 所以在这里我就不写了. 也是为我自己节省时间那嘛, 见谅啦各位