一、今天我们要做的就是这个案例
1.我们今天要做的案例,做好了之后的效果就是这样
这个案例,和昨天那个微博的案例是非常相像的,
哪些相像呢,
1)整体是不是也是能滚动啊,
2)能滚动,它不仅仅是一个UIScrollView
它里面,这个也是一行、两行、三行、四行、
所以说,整体,这也是一个tableView,
今天我们就做这么一个案例,
2.这个整体也是一个tableView,
这个tableView里面,也是我们需要先加载plist数据,然后创建模型,
然后,自定义Cell,把Cell都给它显示到这个上面
这些是不是和我们上次那个微博,都是一样的,
上次微博,也是写模型,懒加载数据,然后呢,自定义Cell,计算坐标,把Cell显示到这个屏幕上,
今天这个也是一样的,只不过后面又给大家多了这么一个,就是,注意,最后一行,现在是在这里,
当我弹出键盘的时候,它并没有挡住这个最后一行,
键盘弹出,键盘并没有把这一行给盖住,
现在这一句话是在这里,键盘弹出之后,键盘并没有把这一行给盖上,而是整个这个UITableView,向上移动,移上来了,
再加这么一个滚动,
我们可以通过“通知”的机制,来实现,
那么,所以说,今天我们就做这一个案例,
把这个案例搞定,就OK了,
3.发一些文字,点击“发送”
发出去以后,它是不是自动给我回一个吧,
它这个就是,不论你发什么,它都回这个字,“滚”
当然我们程序里面,可以改,
你可以改成它,类似于聊天机器人一样,根据预先设定好的一些文字,给它回复一些词,
OK,今天我们就做这么一个案例,
二、在做这个案例的时候,我们首先,
1.有一部分代码,是和我们那个微博,是非常像的,
所以说,在写这个的时候,其实也是在复习微博,
所以说,你脑子里应该把那个概念,上次微博那个实现思路,应该还得有,
然后这里再给大家,简单介绍一下,
我们这个UITableView,你看我在滚动这个UITabView的时候,你看下边这一条儿,
这一条儿,你看它滚动吗,没有随着滚动吧,
那么,你说,最下边的这一条儿,它是在这个UITableView里面的吗,不是吧,
如果说,最下面这一条儿,是在UITableView里面,那么,当你滚动的时候,它是不是会跟随着滚,
就是说,你设置了UITableView的HeaderView、或者是FooterView,
这样的话,当你滚动UITableView的时候,它也会跟着滚,
现在,它没有跟着滚,证明它不是在UITableView里面,
所以说,我们整个这个界面的基本设计,是
1)拽一个普通的一个UIViewController
2)在这个UIViewController上面,放一个UITableView,
3)下面留出44的高度来,
4)然后,在这下面,放一个,底部的放一个UIView,
5)在这个UIView里面,拖一些子控件,
基本上,是这样的一个思路,
那么,上面是一个UITableView,
下面是一个UIView,
分两部分的,来组成的,
3.那么,既然我们这个界面,是分两部分,
上面是一个UITableView,
下面是一个UIView,
所以说,我们这里拽的时候,是不是应该用一个UIViewController,
而不是直接使用一个UITableViewController,
如果直接使用的是UITableViewController,
这样的话,整个界面上的控制器所管理这个View,自身本身就是一个UITableView,
但是我们这里不是,
是上面是UITableView,下面是UIView,
所以说,我们这里,不能用UITableViewController,
要用一个UIViewController,
里面拽两个子控件,一个是上面的UITableView,一个是下面的UIView,
这里是两个子控件,一个是上面的UITableView,一个是下面的UIView,整体是一个UIViewController,
是不是大致上,就是由这么三部分,组成的,
好,那么,接下来,我们就一起来看一下,这个怎么实现,
二、实现这个案例
1.我们一起来建一个,这个项目,我们还是用3.5英寸,
新建一个项目,名字叫做“001QQ聊天界面”
项目前缀,来个“CZ”
然后在这个里面,首先,第一步,要干什么,
是不是先建那个文件夹,
先分组吧,建文件夹,New Group,
我们这里建三个,MVC、Models、Views、Controllers,
再建一个Others,
把这些文件都拖到对应的文件夹里面,
然后,我们基本上,这个分组,是不是已经分完了,
4.紧接着,我们先把那个图片、和素材,拷进来,
我们说,这个程序运行起来之后,首先,是不是有一个启动图片,
然后呢,我们还有一个应用程序图标吧,
看这里,是不是有个应用程序图标,
当你点击的时候,
是不是有个启动图,
所以说,我们先把这个应用程序图标、和启动图,给它拷贝过来,
那么,要拷应用程序图标,在哪里,是不是要找到素材,
素材,在哪里,在这里吧,这里是不是有个QQ聊天这个文件夹,里面有素材,
这个素材里面,AppIcon,就是我们所有的素材,
那么,这些图片,你看,凡是@2x的,是不是都是为那个,我们的视网膜屏幕准备的啊,
每一个大小,大家看,这些图片,每一个大小都不一样,
我们要做的就是,把所有的图片,直接拷到素材里面,拷到我们的项目里面,
找到我们的AppIcon,然后呢,把这一堆,直接拽过来,
拽过来,出现这个绿色加号的时候,就松手,
这样的话,就一一对应了吧,
5.然后,我们要设置启动图,设置启动图,我们直接怎么做呢,
直接,我们先选中项目,
默认,它是不是使用的是这个LaunchScreen.xib,来实现启动图吧,
我们把这里,Use Asset Catalog(使用资产目录),把这里改成,
把这里改成,迁移到使用图片文件夹的方式,
点一下“Migrate”,“迁移”,
然后呢,这里变成了LaunchImage,
然后呢,把下面这个删掉,
OK,删掉以后呢,再打开我们的这个Images.xcassets,文件夹,
发现,这个地方,是不是有一个LaunchImage,文件夹了,
然后,把我们的什么,启动图片,拷进来吧,
这里给大家提醒一下,以后,从xCode6以后开始,iOS8系统里面,
当你拖素材的时候,只要你把图片,拖到这个Images.xcassets文件夹下,那么这个时候,它程序编译的时候,会把所有图片,编译到一个好像是后缀是assets这个文件里面,也就意味着,以后,你下载的那些通过网上,或者通过应用商店里面,下载的那些别人做的应用,你就拿不到他们的图片了,就拿不到他们的图片了,
现在,大家从这个苹果商店,下载的别人的应用,下载下来以后,那个.app,那个Bundle里面,是不是有所有的这个应用所有的素材,是不是都能拷出来,
但是,以后可能就不行了,
所以说,你现在下的那些素材,别扔,
不要删,别说随时我都可以联网下,以后,凡是拖到这个Images.xcassets文件夹里面的图片,编译的时候,会生成一个加密的文件,目前还破解不了,所以说,以后那些图片,你下载下来是拿不到的,
所以说,你现在下载的之前那些版本的,那些就是ipa,那个资源包,不要删,你先留着,说不定以后你就拿不到这个资源图片了,
自己做,你就费劲了,
所以说,大家要注意这个问题,
6.好,接下来,我们把我们的启动图片,现在我们只要把App下载下来,这些图片,是不是都可以盗出来,
然后,把它拽进来,
OK,拽进来以后,注意看,我们再复习一下,
1)这个图片,是为
这个图片,是为了什么程序而生的,
哪个屏幕而用的,
首先,看,是1x,肯定不是视网膜屏幕,那么,在看它的大小,是320乘480,几英寸的,3.5英寸吧,3.5英寸的非视网膜屏幕,
2)这个一看,是2x,
这个一看,2x,是视网膜屏幕吧,
一看它,乘以2以后,是640乘960,那么除以2以后,就是320乘480,
所以说,这个也是为3.5英寸的视网膜屏幕而生的吧,
并且,这两个图片,都是在iOS5,iOS6,下
左边这个是,iOS5下的3.5英寸非视网膜屏幕,
右边这个是,iOS5、iOS6下的3.5英寸视网膜屏幕,
3)然后,再看这个,
这个,它的大小是多大,640乘960吧,那么一看这个640乘960,
肯定就是乘以2以后的,大小,证明它原来也是320乘480,
也就是说,这个也是为3.5英寸的视网膜屏幕而生的,
那么,它的大小,是不是和这个图片,的大小,刚好是一样的,
所以说,我们要把它拽过来,
那么,按住option键,直接把它拖过来,
就OK了,
那么,但是,这个时候,大家会问,为什么同样一张图片,一模一样,都是为视网膜屏幕,3.5英寸的视网膜屏幕,而生的,为什么,要写两个呢,为什么这里要拽两个呢,
一个是为iOS5、iOS6,而生的,一个是为iOS7、iOS8,而生的,
就是说,有可能,它3.5英寸的屏幕,比如说,iPhone4S,它升级到了iOS7、iOS8,是不是也有可能,这个时候,是不是就得用这张图了,
所以说,把这个都拽过来,
4)这个Retina4,一看就是为4英寸的屏幕而生的吧,
4英寸的屏幕,你看一下,640乘1136,
是不是就是iPhone5,iPhone5S,就是320乘568,吧,
320乘568,就是iPhone5,iPhone5S,iPhone5C,等等,
5)那么这个,一看
一看,4.7英寸,肯定是iPhone6,
6)这个一看,
这个一看,是5.5英寸的,肯定是多少,iPhone6plus,吧,
所以说,我们直接把这几个,都拽过来,
是不是就OK了,
大家就可以看这个图,来分析它是哪张图片,
好,把这个启动图,和应用程序图标,拽过来以后,
command + R,运行一下,
哦,先不走,先看一下这个控制器,
控制器现在是多大,
控制器,我们是不是得把它调成3.5英寸的啊,把这里调成什么,iPhone4S吧,
这样的话,我们就看起来,小点儿了,command + R,
看到了吧,启动图有了吧,
对,这就是我们这儿这个东西,好,
7.把这个拽好以后,接下来,我们就把那些素材,拷进来
我们先把我们这个Chat,先把这个图片,也给它拽过来,
拽到我们Image.xcassets下,
所以说,以后,你的项目,不希望别人盗用图片,就把图片拽到这个Images.xcassets下面啊,
这样的话,以后加密了以后,就盗用不了你的图片了,
然后呢,我们这个messages.plist文件,把它拽到我们这个SupportingFiles下面,
OK,好,这样就拽进来了,
这样的话,我们是不是基本素材,就拷进来了,
基本素材拷进来以后,等会儿我们是不是肯定要实现,把这个数据,加载到我们这里,
但是,加载的时候,怎么做呢,我们首先,是不是要把这个数据懒加载起来,
然后呢,我们先把数据懒加载起来,
二、那么,写懒加载的时候,注意看,
1.我还是,观察一下这个messages.plist文件,
里面,整体是一个什么,Array吧,
整体是个Array吧,里面每一个就是一个字典,
我们看,这个字典里面,
分几项,是不是三个键值对儿,
1)第一个,是什么,消息正文,就是你发的QQ消息,text,
2)第二个,是什么,是你这个QQ消息的发送时间,time,
3)第三个,是什么,是你这个类型,type,这个类型,指的是这个消息是“你发的”,还是“对方发的”,
如果说,你给别人发的,这个消息类型,就是“0”,
如果说,是别人给你发的,这个消息类型,就是“1”,
来,给大家看一下我们这里,
大家看一下,比如说,这个,右边是不是你,左边是不是对方吧,
右边是你,你首先发一条消息,那么这个消息的类型,就是”0“,
表示这个是你发的,
然后这个,你又发了一个消息,”问你个严肃的事“,这个是不是又是你发的,
那么这个消息的正文,text,就是“问你个严肃的事”,这是消息的正文,
然后呢,这个消息的,我们看,这个消息的发送时间,
发送时间,就是我们哪里,
发送时间,就是我们这个time,这个键吧,这个time,前边是“前天10:27“,
然后呢,这个消息的类型,就是“0”,因为它是你发的,而下面这个消息,它的类型,就是“1”,是表示对方发的,
所以说,我们这个type,就是表示当前,发送消息的,是谁发的,这就是我们这里这么一个type,
好,接下来,我们就是先把这个模型写好,这个模型,有几个属性,
三个吧,第一个是什么,text,time,type,
2.我们现在来建一个模型,
OK,因为我们这是一个,用来表示消息的模型,所以我们这个模型,就可以叫什么,message,CZMessage,
注意,有人说,这儿是不是要加个s啊,CZMessages,
这个地方,不要加s,因为它表示,模型,这个模型,表示一个对象,一个CZMessage,是不是表示一个对象啊,
所以我们一般模型,不加s,
你说,这儿为什么加s呢,
因为这个文件夹下,是不是有很多个模型啊,
所以,我们这里就是CZMessage,
哦,这是我们示例程序吧,差点儿建错了,我去,这个才是我们写的吧,
这个才是我们写的,是不是里面干干净净的,什么都没有啊,
找到我们模型文件夹,Models,右键,New File,
建一个这个类文件,
名字叫,CZMessage,
点Next,
点击下一步,
然后,在模型里面,是不是三个属性,
那么,三个属性,我就给它写一下吧,我不拷贝,
1)第一个叫什么,text,消息的正文,
//消息的正文
@property(nonatomic,copy)NSString *text;
2)第二个是什么,time,消息发送时间,
//消息发送时间
@property(nonatomic,copy)NSString *time;
3)第三个是什么,type,消息的类型(),
注意,我们在这个plist文件里面,看到类型是一个数字类型啊,
数字类型,是一个0和1,那么我们在写模型的时候,你这里用一个数字类型,0和1,来表示这个消息类型,肯定是没问题的,
0:表示你自己,
1:表示对方,
没有问题,
但是我们这里也可以不用这个0和1,不用这个数字类型,
可以使用一个枚举吧,
枚举,我们学过,那么我问一下大家,使用枚举,我这里消息的类型,就两种,要么是0,,要么是1,0表示自己,1表示对方,
我这里用数字合适,还是用枚举合适,
枚举合适吧,为什么,就是说,如果要是用数字的话,你开发过程当中,比如说,别人要用你这个属性的话,它是不是还得查一下,0表示什么,1表示什么,
他是不是还得查啊,不查还不敢随便写,因为谁知道你这个,0表示什么,1表示什么,
但是用枚举的时候,你在写代码的时候,智能提示,是不是直接就看到这个枚举了,
一看这个枚举,的意思,因为都是字母,都是字母表示的,文字表示,一看这个意思,就知道,第一个枚举表示什么,第二个枚举表示什么,
是不是省的去查开发文档,省的去,再去查这个0表示什么,1表示什么,就是为了开发当中方便,
事实上,枚举,最终就是什么啊,数字吧,
枚举最终就是数字啊,就是数字类型,
所以说它,和数字是一样的,
只不过,开发的过程中,在有限的几个值的时候,用枚举,更方便,仅仅是为了开发更方便,
所以说,我们这个类型,有两个值,我们就用枚举,来表示,
既然要用枚举,是不是要写一个枚举啊,
那么,我请问大家,这个枚举应该写在什么地方,
是不是需要新建一个文件,来写枚举,
不需要吧,为什么,因为你这个枚举,是不是要在这个类当中使用,
用到这个类的时候,才会用到枚举,所以说,可以直接在这个类的头文件的上边,写个枚举啊,
枚举怎么定义,typedef吧,