之一
代码Demo
Github:SYDownloadManager
NSOperationQueue可以方便的实现多任务的处理,对于简单的多任务使用NSBlockOperation和NSInvocationOperation即可很好的处理。但是对于复杂的多任务,比如使用NSURLSession实现下载,使用NSOperationQueue对下载任务进行、开始、暂停、重启、取消以及进度等的操作时,却感觉无从下手。总觉得NSBlockOperation和NSInvocationOperation这两个operation干的是一锤子买卖,就是将下载任务扔到block中或者selector中等待Queue的自动调度,不用进行进度监控,和暂停重启等操作。为学习多线程,解决心中的疑惑,特意结合以前所知所得,实现了该功能,并记录下来,让大家少踩一些坑。
1.断点下载实现原理
利用http请求头 range:bytes=start-end 实现
2.对NSURLSession、NSURLSessionDataTask和NSOperation、NSOperationQueue核心点的理解
首先应该对Queue自动调度Operation有一个初步的了解;每一个Operation有ready(准备状态)、executing(运行状态)、cancled(取消状态)、finished(结束状态)等状态。
其中ready是Queue调用addOperation:后Operation的状态,表明该Operation可以被Queue自动调度,当合适的时机时Operation的start方法会被调用,Operation会处于executing ==yes的状态,切记ready状态是个坑点!!!!
Queue如何获取合适的时机呢??原来Queue是通过KVO来获知Operation的状态,当Operation处于ready时且operationCount小于maxConcurrentOperationCount,就自动调用该Operation的start方法,让这个任务开始运行。
finished状态是表明该Operation已经结束,Queue获取了这个Operation的Finished==YES时,会自动的将该Operation从Queue的队列中移除。这个finished也是个关键点。
其次,对NSURLSession和NSURLSessionTask的认知;一个Session可以个维持若干个Task,Session可以通过回调知道每个task的运行情况比如task的进度,结束后的缓存路径等;而task的开启(resume)、暂停(suspend)、重启(resume)是由自身来控制,且task保留她的这些状态。
这时就可以看到一个共同的相似点,Queue管理Operation,Session管理Task;Queue通过KVO获知Operation的状态,Session可以通过代理获知task的状态。因此,可以把Task和Operation结合(自定义Operation),实现下载任务的手动开启暂停重启等,通过Session的回调获知task的进度,通过Queue自动调度TaskOperation;
3.如何自定义NSOperation
1.要可以下载;TaskOperation有一个NSURLSessionDataTask的属性
2.Queue可以自动开始下载;在TaskOperation中重写start方法,并且启动【dataTask resume】
3.Queue可以获知TaskOperation的下载完成和finished==YES状态,可以在合适的时机自动调用另一个TaskOperation的start方法,又,dataTask并不能获知自己是否下载完毕,所以需要暴露一个completionTask的方法;注意这里finished==yes,且使用KVO
4.cancle方法的重写,在这里记得取消下载任务
5.其他暴露的方法,很清晰。注意每次不论开始还是重启新建一个TaskOperation就可以了。。问我为什么?一个是因为断点的,一个是Queue是会自动移除Operation的
以上自定义NSOperation就完成了,很简单
4.如何实现TaskOperation的调度???
没有实现一说,是自动调度的,只用设置最大并发数并将TaskOperation添加到Queue中就行了,只用记着在Session的Task完成的回调中调用该【TaskOperation completionTask】就行了
SYDownloadTaskManager的一些方法
下载任务完成的回调处理
后续:之二