目录:
- NSURLSession介绍
- 图文介绍
- 下载&解压缩
- 跟踪进度
- 强引用
- 断点续传
一、NSURLSession介绍
NSURLSession是iOS7中新的网络接口,与NSURLConnection是并列的。
当程序在前台时,NSURLSession与NSURLConnection大部分可以互相替代。
NSURLSession支持后台网络操作,除非用户强行关闭
NSURLSession提供的功能:
通过URL将数据下载到内存
通过URL将数据下载到文件系统
将数据上传到指定URL
在后台完成上述功能
对于小型数据,例如用户登录、下载小图像、JSON & XML仍然使用NSURLConnection的异步或同步方法即可
/**
使用NSURLSession肯定是异步,在子线程做耗时操作
我们只需要 创建一个session,发起一个任务,让任务resume就OK了
*/
// 1. url
NSURL *url = [NSURL URLWithString:@"http://192.168.10.9/videos.json"];
// 2. 创建session
// 苹果直接提供了一个全局的session
NSURLSession *session = [NSURLSession sharedSession];
// 3. 由session发起任务
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// 反序列化
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSLog(@"%@", result);
}];
// 4. 需要把任务开始。 默认都是挂起
[task resume];
二、 图文介绍
1.URLSession可以直接通过URL进行请求,他可以下载,上传。
注意:下载他会默认放到tmp文件,uploadTask目前可能还没有完善,不能使用。
2.URLSessionConfigration,用于管理URLSession。
3.最后需要开始任务
三、下载&解压缩
/**
NSURLSession下载,默认将下载的文件保存到tmp目录下。如果回调方法什么事情都没做。tmp里面的东西会自动删除
比如:通常从服务器下载的是压缩包(压缩包会省流量).
当文件下载完成以后,会解压缩。 原始的zip包不需要了。
解压缩也是耗时操作。也需要在子线程执行
*/
//需要导入第三方:SSZipArchive 需要导入框架:lib.dylib
//导入第三方可能会报警告:原因可能用了以前的方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 1. url
NSString *urlStr = @"http://127.0.0.1/itcast/images.zip";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
// 2. 下载
[[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(@"文件的路径%@", location.path);
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"%@", cacheDir);
/**
FileAtPath:要解压缩的文件
Destination: 要解压缩到的路径
*/
[SSZipArchive unzipFileAtPath:location.path toDestination:cacheDir];
}] resume];
}
四、跟踪进度
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 1. url
NSString *urlStr = @"http://127.0.0.1/01-课程概述.mp4";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
// 2. 实例化一个session对象
// Configuration可以配置全局的网络访问的参数
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// 指定回调方法工作的线程
// NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
// NSURLSession 如果不指定线程,默认就是子线程
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
// 发起并且继续任务。
[[session downloadTaskWithURL:url] resume];
}
#pragma mark - NSURLSessionDownloadDelegate
// 1. 下载完成被调用的方法 iOS 7 & iOS 8都必须实现
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下载完成..");
}
// 2. 下载进度变化的时候被调用的。 iOS 8可以不实现
/**
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]);
}
// 3. 短点续传的时候,被调用的。一般什么都不用写 iOS 8可以不实现
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
五、强引用
特别注意:NSURLSession的代理是强引用,所以会有内存管理问题
// @property (nullable, readonly, retain) id delegate;
解决方法一:
#pragma mark - NSURLSessionDownloadDelegate
//代理方法进行任务取消,释放回话
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下载完成..");
// 任务完成,取消NSURLSession
[self.session invalidateAndCancel];
// 释放会话
self.session = nil;
self.downloadTask = nil;
}
解决方法二:
/**视图将要消失的时候,取消session*/
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 任务完成,取消NSURLSession
[self.session invalidateAndCancel];
// 释放会话
self.session = nil;
}
六、断点续传
@interface ViewController ()<NSURLSessionDownloadDelegate>
/**下载任务*/
@property(nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
/**全局管理的会话*/
@property(nonatomic,strong)NSURLSession *session;
/**续传的数据*/
@property(nonatomic,strong)NSData *resumeData;
@end
@implementation ViewController
- (NSURLSession *)session
{
if (_session == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _session;
}
/**继续*/
- (IBAction)resume:(id)sender
{
if (self.resumeData == nil) {
NSLog(@"没有续传的数据");
return;
}
// 使用上一次的记录,新建一个下载任务
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
// 一旦任务建立完成,之前的续传数据没有用,释放掉
self.resumeData = nil;
[self.downloadTask resume];
}
/**暂停*/
- (IBAction)pause:(id)sender
{
NSLog(@"%s", __func__);
[self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
NSLog(@"=----%tu", resumeData.length);
// 保存起来暂停的时候的字节数
self.resumeData = resumeData;
// 释放下载任务
self.downloadTask = nil;
}];
}
- (IBAction)start {
// 1. url
NSString *urlStr = @"http://127.0.0.1/01-课程概述.mp4";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
// 2. 通过session对象 开始一个任务
self.downloadTask = [self.session downloadTaskWithURL:url];
// 继续
[self.downloadTask resume];
}
#pragma mark - NSURLSessionDownloadDelegate
// 1. 下载完成被调用的方法 iOS 7 & iOS 8都必须实现
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下载完成..");
self.downloadTask = nil;
}
// 2. 下载进度变化的时候被调用的。 iOS 8可以不实现
/**
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]);
}
// 3. 断点续传的时候,被调用的。一般什么都不用写 iOS 8可以不实现
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
@end