使用NSURLSession解决下载中的进度跟踪问题,大致步骤如下:
第一步:网址转义。因为网址中如果有中文的话是不可以被服务器识别的。所以要对其进行转义。需要注意的是:下载一般都是GET请求 只有GET请求需要对网址进行转义,POST请求是不需要转义的。使用的转义方法如下:
- (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)enc;
具体使用如下:NSString *urlStr =@"http://127.0.0.1/07-知识点勘误.mp4";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURLURLWithString:urlStr];
第二步:实例化NSURLSession对象。要使用NSURSessionLConfiguration对象来初始化Session对象的方法参数。而对于NSURLSessionConfiguration 也是一个单例类 可以用来配置全局的网络访问参数。具体如下:2.1 新建单例Configuration对象
NSURLSessionConfiguration *session = [NSURLSessionConfiguration defaultSessionConfiguration];
2.2 使用Configuration对象来初始化NSURLSession的构造参数。
NSURLSession *session = [NSURLSessionsessionWithConfiguration:configdelegate:selfdelegateQueue:[NSOperationQueuemainQueue]];
参数:delegateQueue:指定回调方法的执行的线程队列。需要注意的是:苹果已经对此方法进行了封装处理。如果直接传值为nil即默认情况下或传进一个并发操作队列即[[NSOperation alloc] init] ,那么执行代理回调方法的队列就是并发队列会由多个线程异步并发执行。但是如果指定为[NSOperation mainQueue],回调方法只会由主线程队列进行同步执行。
第三步:遵守NSURLSessionDownloadDelegate协议,并实现其回调方法。
此协议的回调方法一共有如下三个回调方法。
第一个方法:当下载完成后才会调用如下方法,IOS7和IOS8都必须实现此方法。
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
第二个方法:下载进度变化的时候会调用如下回调方法,IOS7必须实现,但IOS8可以选择不实现。
/**
bytesWritten: 本次写入的字节数
totalBytesWritten:已经写入的字节数(目前下载的字节数)
totalBytesExpectedToWrite:总得下载字节数(文件的总大小)
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
第三个方法:断点续传的时候会调用如下方法,一般什么都不写。IOS7必须实现,IOS8可以选择不实现。-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)
必须注意的是:由Configuration初始化Session对象后。需要由Session发起并继续任务。因为所有的Session对象默认都是挂起的,必须调用一下resume方法才会开始执行。具体使用如下:
[[session downloadTaskWithURL:url]resume];
具体工程如下:
<span style="font-size:18px;">//
// ViewController.m
// NSURLSession进行下载
//
// Created by apple on 15/10/30.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "ViewController.h"
#import "SSZipArchive.h"
@interface ViewController ()<NSURLSessionDownloadDelegate>
@end
@implementation ViewController
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1 url
NSString *urlStr = @"http://127.0.0.1/07-知识点勘误.mp4";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
// 实例化Session对象
// Configuration 可以配置全局的网络访问参数
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// 指定回调方法执行的线程
/*
其实苹果已经对Session进行了封装,不管delegateQueue是否为全局队列还是nil。代理方法都会在子线程进行异步执行.但是当我们使用主队列时,代理方法只会在主线程执行
*/
// NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init] ];
// NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 发起并继续任务
[[session downloadTaskWithURL:url] resume];
}
#pragma mark- NSURLSessionDownloadDelegate
// 1、 下载完成后被调用的方法 IOS7&IOS8都必须实现的方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下载完成");
}
// 2、 下载进度变化的时候被调用的。 IOS8可以不实现,但IOS7必须实现
/**
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);
NSLog(@"======%@", [NSThread currentThread]);
}
// 3、断点续传的时候,被调用的方法。一般什么都不写,IOS8可以不实现,但IOS7必须实现
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
@end</span>
运行结果如下:
只打印进度时,输出如下:
屏蔽打印进度的代码,当传值为并发操作队列时,打印如下:
当传值为nil时,打印执行代理方法的线程如下:
当传值为操作主线程时,打印执行代理方法的线程如下: