能够实现下载 暂停 继续下载功能 主要使用 NSURLSessionDownloadTask
在要实现ViewController 的.m 文件中实现如下代码:
核心代码
需要遵循 <NSURLSessionDownloadDelegate> 代理 实现里面的协议方法
匿名类别中需要实现
#import "ViewController.h"
//引入其他文件中声明的全局变量时,使用extern 关键字
extern void(^compeleHandle)();
@interface ViewController ()<NSURLSessionDownloadDelegate>
@property (weak, nonatomic) IBOutlet UIButton *downloadBtn;
@property (weak, nonatomic) IBOutlet UIProgressView *progess;
@property(nonatomic, strong) NSURLSession *session;//执行下载任务的session
@property (nonatomic, strong) NSURLSessionDownloadTask *task;//下载任务
@property (nonatomic, strong) NSData * resumData;//暂停时,产生的已经下载的数据,用于再次启动继续下载
@end
在viewDidLoad 需要实现代码
- (void)viewDidLoad {
[super viewDidLoad];
//修改进度条的高度
self.progess.transform = CGAffineTransformMakeScale(1, 3);
self.progess.progress = 0;
}
点击下载按钮代码
//下载
- (IBAction)downloadClicked:(UIButton *)sender {
sender.enabled = NO;
//下载的资源路径
NSURL * url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V4.0.2.dmg"];
//创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
if(!_session){
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"downloadID"];
//创建后台模式的session
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
if(self.resumData != nil){
//在上一次下载的基础上继续下载
//在上一次下载的基础上创建任务
_task = [_session downloadTaskWithResumeData:_resumData];
}else{
//新建任务下载
//创建任务
_task = [_session downloadTaskWithRequest:request];
}
//启动下载任务
[_task resume];
}
点击暂停按钮代码
//暂停
- (IBAction)pauseClicked:(UIButton *)sender {
//任务的的暂停
[_task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//当前已经下载的数据:保存当前已经下载的数据,便于做续传
_resumData = resumeData;
//停不下来
[_session invalidateAndCancel];//让会话实现并取消任务
_session = nil;
}];
[self.downloadBtn setTitle:@"继续" forState:UIControlStateNormal];
self.downloadBtn.enabled = YES;
}
下载协议方法
//已经开始从某一个偏移量的位置下载
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"已经开始下载,开始的偏移量----> %lld",fileOffset);
}
//下载过程中调用的方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
//下载过程中我们是得不到所下载的数据的,我们只能更新下载进度
NSLog(@"更新下载进度");
//计算当前的下载进度
// bytesWritten: 本次写入的数据长度
// totalBytesWritten: 已经下载的数据总长度
// totalBytesExpectedToWrite 数据的总长度
// 进度 =(bytesWritten + totalBytesWritten)÷ totalBytesExpectedToWrite
CGFloat progress = (bytesWritten + totalBytesWritten)* 1.0/ totalBytesExpectedToWrite * 1.0 ;
//更新进度条显示的进度值
dispatch_async(dispatch_get_main_queue(), ^{
//更UI相关的更新,要在主线程中完成
self.progess.progress = progress;
});
}
//下载结束
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
//下载完成,所下载的数据存放在 location 位置,我们可以通过文件操作,移动这个数据到我们需要的位置
NSLog(@"下载完成");
NSFileManager *fm = [NSFileManager defaultManager];
//将要移动的目标位置,沙盒路径中的存放位置
NSString * path = [NSString stringWithFormat:@"%@/Documents/QQ.dmg",NSHomeDirectory()];
NSError *error = nil;
[fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:&error];
if(!error){
NSLog(@"移动成功,可以到沙盒路径下查看下载的文件");
self.progess.progress = 1.0;
}
}
//如果要支持后台下载,实现后台处理的协议方法
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
//下载结束时,后台唤醒App之后,应该回调的第一个协议方法
NSLog(@"后台下载完成,回调协议方法");
if(compeleHandle){
//回调,使得其他的后续的协议方法能正常调用
compeleHandle();
//通常在这儿,要结合本地推送使用,否则用户本身是发现不了任务执行完成的
}
}
需要在AppDelegate 的.m 中实现代码
#import "AppDelegate.h"
void(^compeleHandle)();//用于后台任务完成时记录回调block
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
//让App支持后台处理任务,实现AppDelegate的后台处理协议方法
-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
//在后台执行的后台任务完成之后,首先调用的方法,通过该方法来唤醒APP
//将block记录下
compeleHandle = completionHandler;
}
网友评论