IOS 开发进阶--多线程和网络--NSURLSession详细解
@implementation ViewController
/**
NSURLSession 提供的断点续传存在的问题,不能"停",应用程序不能终止,一旦终止,续传数据就丢失了,下次还需要重头再来!
*/
/// 开始
- (IBAction)start {
// 1. url
NSURL *url = [NSURL URLWithString:@"/qqfile/QQforMac/QQ_V4.0."];
// 直接启动任务,可以通过代理跟踪进度
= [ downloadTaskWithURL:url]; // 发起下载会话
[ resume]; // 启动任务
}
/// 暂停 - 下载任务
- (IBAction)pause {
NSLog(@"暂停");
// 使用需要续传的数据,暂停下载任务
// 暂停方法,只需要执行一次,被暂停就不用再次暂停
// 在运行的时候,可以个 nil 发送消息,但是不会执行
/**
1. 所有的任务都是由会话发起的
2. 当任务启动后,会话会对任务进行强引用
3. 一旦任务被取消,意味着会话不再引用任务,一个 weak 对象没有其他对象强引用,会被立即释放
4. 如果属性 是 strong,除了会话之外,vc同样对任务强引用(session 为什么要使用强引用)
提问:自己开发,用 strong!
*/
// 这个是取消下载任务 (达到暂停的目的)
[ cancelByProducingResumeData:^(NSData *resumeData) {
NSLog(@"---> %tu", resumeData);
// 记录续传数据
= resumeData; // 将暂停时候的数据保存起来(如果不保存下次启动的时候是没有数据的)
// 释放了下载任务
= nil; // 将下地任务释放避免多次暂停的问题
}];
}
/// 继续
- (IBAction)resume {
// 需要避免下载任务重复创建
if ( == nil) {
NSLog(@"没有续传数据");
return;
}
// 使用续传数据,重新实例化下载任务
// 一旦续传的下载任务被建立之后,续传数据就没有用了!
= [ downloadTaskWithResumeData:];
= nil;
[ resume];
}
// MARK: 下载代理方法
/// 提示:如果是 iOS 7.0 开发,三个代理方法都是必须实现的
/// 下载完成 - 必须要实现的
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
NSLog(@"%@", location);
}
/// 断点续传的代理方法,可以什么都不写
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
NSLog(@"%s", __FUNCTION__);
}
/**
bytesWritten 本次下载字节数
totalBytesWritten 已经下载字节数
totalBytesExpectedToWrite 总字节数,文件大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
// 这里设置的进度条
float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f %@", progress, [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
= progress;
});
}
// MARK: - 懒加载
- (NSURLSession *)session {
if (_session == nil) {
// 网络会话的配置
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
/**
下载本身是异步的,并不会阻塞主线程的工作!
"代理"的队列 - 只是指定了代理执行所在的队列!
- [[NSOperationQueue alloc] init]
* 所有的代理回调,都是异步的
- nil(效果等同于自定义队列 - 斯坦福大学白胡子老头说的使用 nil)
* 所有的代理回调,都是异步的
- 主队列
* 所有的代理回调,都是在主线程异步的,不会阻塞主线程执行!
* 提示:下载回调会非常频繁,如果有很多文件同时下载,同时回调,还是会影响到主线程的!
* 队列的选择
- 如果完成之后,直接更新 UI,选择主队列
- 如果完成之后,要做后续的耗时(解压缩)操作,使用nil
*/
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _session;
}
@end