实现:Cell图片下载程序
源代码下载地址:点击打开链接
1、Cell图片下载程序
1.1 界面
1.2 基本思路
1> Storyboard中添加导航控制器,根控制器为UITableViewController
2> 新建HMAppsViewController,关联
3> 导入app.plist,新建HMApp,提供类方法,利用KVC,字典转模型
4>HMAPPViewController中懒加载模型数组
5> 实现ViewController数据源方法,设置Cell的textLabel和detailTextLabel,并测试
6> 图片下载问题
1.3 Cell图片下载思路 --- 重要
1> 若直接在设置Cell明细的代理方法(主线程)中,下载图片,设置每个Cell图片
注1:dataWithContentsOfURL:从网络上下载图片,耗时,而且放在主线程中,会造成主线程阻塞,导致拖动变卡(同时网速慢,在下载图片的同时不能拖动界面)
注2:设置Cell明细的代理方法,调用频率非常高(一滚动只要出现新的Cell就会调用),上下滚时会导致重复下载,浪费流量
2> 使用NSOperation作为下载线程,且系统会管理下载的线程数
3> 懒加载一个NSOperationQueue,用来存放所有下载操作的队列
注1:由于异步执行,很有可能图片还没有下载完,这个Cell就已经返回,还是会导致图片没有显示,来回滚动后可能会显示
注2:应保证图片下载完,设置了Cell以后再返回Cell
4> 首先解决重复下载问题
保证:1张图片只下载1次
即:每一个url对应的Operation只需要一个,一个Operation代表一个下载操作,一对一的对应关系,使用字典!!!
1. 懒加载一个NSMutableDictionary,用于存放所有的下载操作(url是key,Operation对象是value)
2. 在Cell明细方法中,首先判断对应key的Operation是否存在,若不存在则创建对应的Operation,开启下载线程,并将Operation添加到字典中
注:由于是异步执行,添加到队列后,又将Operation添加到字典中,此时用户如果又来回滚动的话,即使下载还没有完成,也不会再去创建新的Operation
5> 此时又会出现两个问题:
1. 存放操作的字典operations会越来越大
2. 如果下载失败,一旦出现一次,该图片就无法再重新下载,因为这个图片url对应的Operation一直存在字典中
解决办法:
1.
下载完后,将操作Operation从字典中移除2.
此时又导致之前的问题,又会重新下载3.
因此,再添加一个字典images(懒加载),存放已经下载完的UIImage,可以保证以后需要的时候直接从内存中取,不用再下载4. Cell明细方法中,应该首先判断images字典中是否已经存在下载好的图片,若无,再去下载,同时再根据operations字典保证不要重复下载
5.
此时若下载失败,images字典中不存在对应的UIImage图片,而且对应的Operation已经移除,可以重新下载注:字典不能放nil,因此万一图片下载失败
self.images[app.icon]= image;会导致程序崩溃
需加判断
if (image) {
self.images[app.icon]= image;
}
6> 缓存池可重用问题
注:0、1、2、3是已经下载完的图片,当用户向上拖动时,0被放入缓存池中,此时4进入界面,会从缓存池中加载可重用Cell-0,由于4还没有下载,若4来不及下载完成,不能及时设置Cell-4图片会造成:0的图片显示在4的位置!!!等到4的图片下载完成,再设置回4对应的图片
解决办法:
使用占位图片,在图片未下载完成的时候使用占位图片盖住,代表正在下载,下载完成后设置为相应图片,且下次会直接使用下载好的图片
7> 图片显示错乱问题
还是Cell的循环利用导致,原因如下:
一开始0对应的图片在下载中,用户拖动后,将0放到了缓存池中,4出现的时候,从缓存池中取出了0放到了4的位置,并发送请求下载4对应的图片,此时一开始0对应的图片刚好下载完成,会到主线程中设置0对应Cell的图片,此时由于Cell-0和Cell-4对应同一个地址,就会将0的图片设置到4的位置,造成显示错乱,等到4对应图片又下载完成后,再重新设置回4!
解决办法:不能直接设置Cell图片,应该重新刷新表格,此时又会调用Cell明细方法,而此时已经有对应的正确图片
此时,基本完成Cell图片下载,保证指下载一次,且以后每次都从缓存中取出图片来显示,拖动tableView也不会卡!
8> 添加内存警告处理
9> 添加开始滚动和滚动结束的队列处理
10> 抽取下载代码
11> 整体思路
12> block循环引用问题
注1:block会对里面的对象进行强引用
注2:此时由于block和self(HMAppsViewController)循环引用,都不能释放
解决办法:block内部使用弱指针
13> 整体代码
1.4 沙盒缓存
1> 将图片存入沙盒
2> 从沙盒中取出图片
2、自定义Operation
将操作中需要执行的操作封装到一个自定义Operation中,如上述Cell图片下载程序中的下载操作
注1:一旦将一个操作添加到队列当中,其实内部会调用这个操作的main方法
注2:下载完应该通知控制器去刷新表格,使用代理
3、SDWebImage --- 重要
以Cell图片下载程序为例:
1> #import"UIImageView+WebCache.h"
2> 在Cell明细方法中调用方法即可,实现上述图片下载所有操作
3> 其他常用用法
4>SDWebImage内存处理
注:SDWebImage通常属于整个项目,不属于某个控制器(很多控制器都需要使用这个框架),因此需要在整个项目(appDelegate)有内存警告的时候进行内存处理(#import "SDWebImageManager.h")
4、小结
注:SDWebImage缓存时长默认一周
5、网络基础
5.1 简单说明
在移动互联网时代,移动应用的特征有:几乎所有应用都需要用到网络,比如QQ、微博、网易新闻、优酷、百度地图;只有通过网络跟外界进行数据交互、数据更新,应用才能保持新鲜、活力;如果没有了网络,也就缺少了数据变化,无论外观多么华丽,终将变成一潭死水
移动网络应用 = 良好的UI + 良好的用户体验 + 实时更新的数据
新闻:网易新闻、新浪新闻、搜狐新闻、腾讯新闻
视频:优酷、百度视频、搜狐视频、爱奇艺视频
音乐:QQ音乐、百度音乐、酷狗音乐、酷我音乐
LBS:百度地图、高德地图、大众点评、墨迹天气、滴滴打车
电商:淘宝、京东商城、天猫、蘑菇街、凡客诚品、美丽说
社交:QQ、微信、微博、陌陌、比邻
为什么要学习网络编程
网络编程是一种实时更新应用数据的常用手段
网络编程是开发优秀网络应用的前提和基础
5.2 基本概念
在网络编程中,有几个必须掌握的基本概念
客户端(Client):移动应用(iOS、android等应用)
服务器(Server):为客户端提供服务、提供数据、提供资源的机器
请求(Request):客户端向服务器索取数据的一种行为
响应(Response):服务器对客户端的请求做出的反应,一般指返回数据给客户端
作为移动开发工程师,主要的精力都是放在前端开发
5.3 服务器
1> 服务器分类
2> 本地服务器选择
3> 搭建本地服务器
参考博客:点击打开链接
4> 本地服务器的主机地址
6、URL
注:URL中常见的协议
1> HTTP
超文本传输协议,访问的是远程的网络资源,格式是http://
http协议是在网络开发中最常用的协议
2> file
访问的是本地计算机上的资源,格式是file://(不用加主机地址)
3> mailto
访问的是电子邮件地址,格式是mailto:
4> FTP
访问的是共享主机的文件资源,格式是ftp://
7、HTTP协议
1> HTTP协议(全称是Hypertext Transfer Protocol,超文本传输协议)简介:不管是移动客户端还是PC端,访问远程的网络资源经常使用HTTP协议(访问百度主页:http://www.baidu.com)
2>HTTP协议特点
1. 简单快速 因为HTTP协议简单,所以HTTP服务器的程序规模小,因而通信速度很快
2. 灵活 HTTP允许传输任意类型的数据
3. HTTP 0.9和1.0使用非持续连接,限制每次连接只处理一个请求,服务器对客户端的请求做出响应后,马上断开连接,这种方式可以节省传输时间
3> HTTP的通信过程
要想使用HTTP协议向服务器索取数据,得先了解HTTP通信的完整过程,完整的http通信可以分为2大步骤
1. 请求:客户端向服务器索要数据
2. 响应:服务器返回客户端相应的数据
4> iOS中发送HTTP请求的方案