URLSession
1,随便说一下URLSession
,这个类比之前的URLConnection
下载数据或者文件,特别是大文件,App
的内存和性能提升很多,不会急剧暴增。
URLSession
的构造方法
//单例
@property (class, readonly, strong) NSURLSession *sharedSession;
//便利构造器
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
接下来的一句话非常重要!!
URLSession
所有的网络都是Session
发起的。而且所有的任务默认是挂起的,需要调用resume
。
先记住这句话,等下会说到。
2,使用单例Session
self.session = [NSURLSession sharedSession];
[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}] resume];
你会发现这个方法,没办法设置
delegate
,就是你只能用Block
回调。
这是因为单例构造的Session
是系统全局的。设置delegate
会出现你意想不到的事情,比A-App
和B-App
,两个App
同时对单例设置了delegate
,delegate
是一对一映射,那么可能A-App
的数据可能会返还给B-App
。这个可能很多文章都有提到过
[[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",location);
}] resume];
Session
的下载文件会暂存到沙盒路径的tmp
里面,所以如果下载完成我们不主动去写入别的Path
,那么文件很可能就消失了,系统会自动回收这块区域。
3,如果你使用便利构造器方法
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
- 这里
delegateQueue
可以设置nil
,默认就是异步队列 - 要注意
Session
对delegate
是强引用,要手动Cancle
或者Finish
。
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSLog(@"完成 %@",location);
//完成任务,
[self.session finishTasksAndInvalidate];
//置空Session
self.session = nil;
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
//取消会话
[self.session invalidateAndCancel];
self.session = nil;
}
不然dealloc
不会调用的。
4,Session的断点续传
- (IBAction)pause:(id)sender {
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//resumeData : 已下载的数据
self.resumeData = resumeData;
//释放下载任务
self.downloadTask = nil;
}];
}
- (IBAction)resume:(id)sender {
//没有续传任务
if (self.resumeData == nil) {
return;
}
//续传任务
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
//清空续传数据
self.resumeData = nil;
//所有的任务都是默认挂起的!!
[self.downloadTask resume];
}