/** 当前会话*/
@property (nonatomic,strong) NSURLSession *currentSession;
/** 后台会话*/
@property (nonatomic,strong) NSURLSession *backgroundSession;
/** 及时会话*/
@property (nonatomic,strong) NSURLSession *ephemeralSession;
/** 可恢复的下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *canResumeTask;
/** 可取消的下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *canCancelTask;
/** 后台下载任务*/
@property (nonatomic,strong) NSURLSessionDownloadTask *backgroundTask;
/** 用于保存可恢复任务的数据*/
@property (nonatomic,strong) NSData *resumeData;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
/** 创建当前的session*/
- (void)createCurrentSession {
// 使用默认的会话配置器
NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
// 创建会话
NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];
self.currentSession = session;
// 给其一个描述,即标签
self.currentSession.sessionDescription = @"kCurrentSession";
}
/**取消*/
- (IBAction)cancel:(id)sender {
// 取消下载(如果任务存在,取消任务,指针设为nil)
if(self.canCancelTask) {
[self.canCancelTask cancel];
self.canCancelTask = nil;
}
NSLog(@"取消了下载:%@",nil);
}
/**开始*/
- (IBAction)start:(id)sender {
// 创建会话(默认的会话配置器,并且给会话添加描述),设置请求,session分配任务(创建任务),执行任务
if (self.currentSession == nil) {
// 如果没有则创建
[self createCurrentSession];
}
NSString *imageUrl = Base_Url;
// 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
// 下载任务
self.canCancelTask = [self.currentSession downloadTaskWithRequest:request];
self.imageView.image = nil;
// 执行下载任务
[self.canCancelTask resume];
}
#pragma mark - 可断点续传的任务
/**恢复*/
- (IBAction)resumeTask:(id)sender {
NSString *imageUrl = Base_Url;
// 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
// 如果可恢复的下载任务为空,创建任务,并且创新连接会话(创建),
if (self.canResumeTask == nil && self.currentSession == nil) {
[self createCurrentSession];
}
if (self.resumeData) {
// 从当前已经有的数据基础上开始下载 downloadTaskWithResumeData
self.canResumeTask = [self.currentSession downloadTaskWithResumeData:self.resumeData];
} else { // 没有已保存的数据
self.resumeData = [NSData data];
self.canResumeTask = [self.currentSession downloadTaskWithRequest:request];
}
[self.canResumeTask resume];
}
/**暂停*/
- (IBAction)pauseTask:(id)sender {
NSLog(@"中断下载:%@",nil);
if (self.canResumeTask) { // 如果当前任务存在,保存数据,并且取消任务,
[self.canResumeTask cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData;
self.canResumeTask = nil;
}];
}
}
#pragma mark - NSURLSessionDownloadDelegate '下载类代理方法'
/**请求数据完成调用*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
NSLog(@"%s",__func__);
NSData *data = [NSData dataWithContentsOfURL:location];
// 请求数据完成,回主线程=显示UI
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = [UIImage imageWithData:data];
});
}
/**数据写入*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
// 每次断点续传 传入的文件数据 数量
NSLog(@"bytesWritten--%lld",bytesWritten);
// 已经写入的文件数据大小
NSLog(@"totalBytesWritten--%lld",totalBytesWritten);
// 总共期望传入的文件数据大小
NSLog(@"totalBytesExpectedToWrite--%lld",totalBytesExpectedToWrite);
// 通过这个方法可以获取接收数据的进度 float progress = totalBytesWritten/totalBytesExpectedToWrite;
}
// Sent when a download has been resumed. 类似断点续传
// 在恢复下载的时候调用,从fileOffset位置处恢复下载
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes {
// 文件恢复下载的偏移量,即文件中数据的位置
NSLog(@"fileOffset--%lld",fileOffset);
}
#pragma mark - NSURLSession ‘代理方法‘
// 无论成功或者失败 这个方法都会调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
NSLog(@"error:%@",error);
}
// 完成了后台下载任务
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
NSLog(@"%s",__func__);
// 得到应用程序代理
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
//
if (self.currentSession == session) {
// 应用程序用一个block中间变量保存 程序完成的block
if(appDelegate.backgroundSessioCompletionHandler) {
void (^handler)() = appDelegate.backgroundSessioCompletionHandler;
appDelegate.backgroundSessioCompletionHandler = nil;
// 应用程序收到
handler();
}
}
}
#pragma mark - 后台下载
- (NSURLSession *)backgroundSession {
// 单例形式的后台会话
static NSURLSession *backgroundSession = nil;
//这里用GCD一次性代码创建一个后台会话单例,并设置会话描述
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *bgConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"background"];
// 创建会话 后台会话配置器
backgroundSession = [NSURLSession sessionWithConfiguration:bgConfig delegate:self delegateQueue:nil];
backgroundSession.sessionDescription = @"background";
});
return backgroundSession;
}
- (IBAction)backgroundTask:(id)sender {
if (self.currentSession == nil) {
self.currentSession = [self backgroundSession];
}
NSString *imageUrl = Base_Url;
// 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
self.backgroundTask = [self.currentSession downloadTaskWithRequest:request];
// 开始执行后台下载任务
[self.backgroundTask resume];
}
@property (copy,nonatomic) void(^backgroundSessioCompletionHandler)(void);
/**
* 后台下载完成后,程序被唤醒,该方法被调用
*/
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
NSLog(@"%s",__func__);
self.backgroundSessioCompletionHandler = completionHandler;
}