下载管理类 FGGDownloadManager.h
首先要导入下载类:#import "FGGDownloader.h"
单例接口
+(instancetype)shredManager;
同样有添加下载任务的接口:
/**
* 断点下载
*
* @param urlString 下载的链接
* @param destinationPath 下载的文件的保存路径
* @param process 下载过程中回调的代码块,会多次调用
* @param completion 下载完成回调的代码块
* @param failure 下载失败的回调代码块
*/
-(void)downloadWithUrlString:(NSString *)urlString
toPath:(NSString *)destinationPath
process:(ProcessHandle)process
completion:(CompletionHandle)completion
failure:(FailureHandle)failure;
管理类自然可以暂停指定的某个下载,根据某个下载链接url,暂停某个下载
/**
* 暂停下载
*
* @param url 下载的链接
*/
-(void)cancelDownloadTask:(NSString *)url;
管理类可以暂停所有下载任务:
/**
* 暂停所有下载
*/
-(void)cancelAllTasks;
管理类可以彻底移除某个下载任务:
/**
* 彻底移除下载任务
*
* @param url 下载链接
* @param path 文件路径
*/
-(void)removeForUrl:(NSString *)url file:(NSString *)path;
当然管理类可以根据下载链接url获取上一次的下载进度:
/**
* 获取上一次的下载进度
*
* @param url 下载链接
*
* @return 下载进度
*/
-(float)lastProgress:(NSString *)url;
以及获取文件大小信息:
/**
* 获取文件已下载的大小和总大小,格式为:已经下载的大小/文件总大小,如:12.00M/100.00M。
*
* @param url 下载链接
*
* @return 有文件大小及总大小组成的字符串
*/
-(NSString *)filesSize:(NSString *)url;
管理类的实现 FGGDownloadManager.m
- 在这里,我们搞了一个队列,设置了同时最多允许多少个下载任务。
- 超过最大下载任务后,添加下载任务将会被添加进入下载任务队列,处于等待模式。
- 当当前正在进行的下载任务数小于允许最大同时下载任务数时,队列中的一个下载任务出列(遵循先入列的先出列)。
根据逻辑,我定制了以下成员变量
@implementation FGGDownloadManager{
NSMutableDictionary *_taskDict;
/**
* 排队对列
*/
NSMutableArray *_queue;
/**
* 后台进程id
*/
UIBackgroundTaskIdentifier _backgroudTaskId;
}
单例方法:
+(instancetype)shredManager
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mgr=[[FGGDownloadManager alloc]init];
});
return mgr;
}
初始化的时候,注册app进入后台,app会到前台,被终结等,以及系统内存不足的通知:
-(instancetype)init{
if(self=[super init]){
_taskDict=[NSMutableDictionary dictionary];
_queue=[NSMutableArray array];
_backgroudTaskId=UIBackgroundTaskInvalid;
//注册系统内存不足的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(systemSpaceInsufficient:) name:FGGInsufficientSystemSpaceNotification object:nil];
//注册程序下载完成的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadTaskDidFinishDownloading:) name:FGGDownloadTaskDidFinishDownloadingNotification object:nil];
//注册程序即将失去焦点的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadTaskWillResign:) name:UIApplicationWillResignActiveNotification object:nil];
//注册程序获得焦点的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadTaskDidBecomActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
//注册程序即将被终结的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadTaskWillBeTerminate:) name:UIApplicationWillTerminateNotification object:nil];
}
return self;
}
收到系统内存不足的通知时,取消下载:
/**
* 收到系统存储空间不足的通知调用的方法
*
* @param sender 系统存储空间不足的通知
*/
-(void)systemSpaceInsufficient:(NSNotification *)sender{
NSString *urlString=[sender.userInfo objectForKey:@"urlString"];
[[FGGDownloadManager shredManager] cancelDownloadTask:urlString];
}
程序即将失去焦点,开启后台:
/**
* 收到程序即将失去焦点的通知,开启后台运行
*
* @param sender 通知
*/
-(void)downloadTaskWillResign:(NSNotification *)sender{
if(_taskDict.count>0){
_backgroudTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
}];
}
}
程序重新获得焦点时,关闭后台:
/**
* 收到程序重新得到焦点的通知,关闭后台
*
* @param sender 通知
*/
-(void)downloadTaskDidBecomActive:(NSNotification *)sender{
if(_backgroudTaskId!=UIBackgroundTaskInvalid){
[[UIApplication sharedApplication] endBackgroundTask:_backgroudTaskId];
_backgroudTaskId=UIBackgroundTaskInvalid;
}
}
程序即将被终结时,取消所有下载任务:
/**
* 程序将要结束时,取消下载
*
* @param sender 通知
*/
-(void)downloadTaskWillBeTerminate:(NSNotification *)sender{
[[FGGDownloadManager shredManager] cancelAllTasks];
}
收到下载完成的通知时,从排队队列中取出一个任务出列:
/**
* 下载完成通知调用的方法
*
* @param sender 通知
*/
-(void)downloadTaskDidFinishDownloading:(NSNotification *)sender{
//下载完成后,从任务列表中移除下载任务,若总任务数小于最大同时下载任务数,
//则从排队对列中取出一个任务,进入下载
NSString *urlString=[sender.userInfo objectForKey:@"urlString"];
[_taskDict removeObjectForKey:urlString];
if(_taskDict.count<kFGGDwonloadMaxTaskCount){
if(_queue.count>0){
NSDictionary *first=[_queue objectAtIndex:0];
[self downloadWithUrlString:first[@"urlString"]
toPath:first[@"destinationPath"]
process:first[@"process"]
completion:first[@"completion"]
failure:first[@"failure"]];
//从排队对列中移除一个下载任务
[_queue removeObjectAtIndex:0];
}
}
}
添加下载任务:判断是否超过允许的最大的并发任务数,若大于,则进入队列派对,反之则搞一个下载类去下载这个任务:
-(void)downloadWithUrlString:(NSString *)urlString toPath:(NSString *)destinationPath process:(ProcessHandle)process completion:(CompletionHandle)completion failure:(FailureHandle)failure{
//若同时下载的任务数超过最大同时下载任务数,
//则把下载任务存入对列,在下载完成后,自动进入下载。
if(_taskDict.count>=kFGGDwonloadMaxTaskCount){
NSDictionary *dict=@{@"urlString":urlString,
@"destinationPath":destinationPath,
@"process":process,
@"completion":completion,
@"failure":failure};
[_queue addObject:dict];
return;
}
FGGDownloader *downloader=[FGGDownloader downloader];
@synchronized (self) {
[_taskDict setObject:downloader forKey:urlString];
}
[downloader downloadWithUrlString:urlString
toPath:destinationPath
process:process
completion:completion
failure:failure];
}
取消下载任务:
/**
* 取消下载任务
*
* @param url 下载的链接
*/
-(void)cancelDownloadTask:(NSString *)url{
FGGDownloader *downloader=[_taskDict objectForKey:url];
[downloader cancel];
@synchronized (self) {
[_taskDict removeObjectForKey:url];
}
if(_queue.count>0){
NSDictionary *first=[_queue objectAtIndex:0];
[self downloadWithUrlString:first[@"urlString"]
toPath:first[@"destinationPath"]
process:first[@"process"]
completion:first[@"completion"]
failure:first[@"failure"]];
//从排队对列中移除一个下载任务
[_queue removeObjectAtIndex:0];
}
}
取消所有下载任务:
-(void)cancelAllTasks{
[_taskDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
FGGDownloader *downloader=obj;
[downloader cancel];
[_taskDict removeObjectForKey:key];
}];
}
彻底移除下载任务:
/**
* 彻底移除下载任务
*
* @param url 下载链接
* @param path 文件路径
*/
-(void)removeForUrl:(NSString *)url file:(NSString *)path{
FGGDownloader *downloader=[_taskDict objectForKey:url];
if(downloader){
[downloader cancel];
}
@synchronized (self) {
[_taskDict removeObjectForKey:url];
}
NSUserDefaults *usd=[NSUserDefaults standardUserDefaults];
NSString *totalLebgthKey=[NSString stringWithFormat:@"%@totalLength",url];
NSString *progressKey=[NSString stringWithFormat:@"%@progress",url];
[usd removeObjectForKey:totalLebgthKey];
[usd removeObjectForKey:progressKey];
[usd synchronize];
NSFileManager *fileManager=[NSFileManager defaultManager];
BOOL fileExist=[fileManager fileExistsAtPath:path];
if(fileExist){
[fileManager removeItemAtPath:path error:nil];
}
}
根据url获取上次下载进度:
-(float)lastProgress:(NSString *)url{
return [FGGDownloader lastProgress:url];
}
根据url获取上次下载大小:
-(NSString *)filesSize:(NSString *)url{
return [FGGDownloader filesSize:url];
}
最后在销毁的时候,移除通知:
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
最后附上我的GitHub代码地址:FGGDownloader,欢迎pull request和star ~
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦