NSURLSession

iOS URL系统概述:

The URL loading system includes classes that load URLs along with a number of important helper classes that work with those URL loading classes to modify their behavior. The major helper classes fall into five categories: protocol support, authentication and credentials, cookie storage, configuration management, and cache management.(URL加载系统包括URL加载类和一些辅助类,这些辅助类完善URL加载类的操作)

1.URL支持的协议:
The URL loading system provides support for accessing resources using the following protocols:ftp:,http:,https:,data:,file:
It also transparently supports both proxy servers and SOCKS gateways using the user’s system preferences.
(URL:统一资源定位符(uniform resource locator),是在网络中定位资源位置的表示方法.
组成:协议/服务器/路径/文件名;协议(schema)包括http,https,ftp,mail,file,telnet等)
URLloadsystem
2.URL加载类的区别

  • Using the NSURLSession class to asynchronously fetch the contents of a URL to memory or download files to disk in iOS 7 and later or OS X v10.9 and later
  • Using NSURLConnection to asynchronously fetch the contents of a URL to memory in older versions of iOS or OS X.
  • Using NSURLDownload to download files asynchronously to disk in older versions of OS X.

    NSURLSession

    1.NSURLSession Class

  • NSURLSession—A session object.
  • NSURLSessionConfiguration—A configuration object used when initializing the session.
  • NSURLSessionTask—The base class for tasks within a session.
  • : NSURLSessionDataTask—A task for retrieving the contents of a URL as an NSData object
  • :: NSURLSessionUploadTask—A task for uploading a file, then retrieving the contents of a URL as an NSData object
  • : NSURLSessionDownloadTask—A task for retrieving the contents of a URL as a temporary file on disk

    NSURLSession Protocol

  • NSURLSessionDelegate
  • :NSURLSessionTaskDelegate<NSURLSessionDelegate>
  • ::NSURLSessionDataDelegate<NSURLSessionTaskDelegate>
  • ::NSURLSessionDownloadDelegate<NSURLSessionTaskDelegate>

    2.Use NSURLSession

  • 1) Create a session configuration.

    1
    [NSURLSessionConfiguration defaultSessionConfiguration]
  • 2) Create a session, specifying a configuration object and, optionally, a delegate.

    1
    2
    3
    4
    sessionWithConfiguration:
    //根据创建的Configuration创建一个Session,系统默认创建一个新的OperationQueue处理Session的消息。
    sessionWithConfiguration:delegate:delegateQueue:
    //设定回调的delegate(这个delegate会被强引用),并设定delegate在哪个OperationQueue回调,如果设置为[NSOperationQueue mainQueue]就能在主线程进行回调非常的方便。
  • 3) Create task objects within a session that each represent a resource request

    1
    2
    3
    4
    5
    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
    - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
    - (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
    - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
    NSURLSessionDownloadTask *task = [NSURLSession downloadTaskWithURL:url]
  • 4) Call its delegate methods.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //NSURLSessionTaskDelegate 
    - (void)URLSession:task:didCompleteWithError:
    //NSURLSessionDataDelegate
    - (void)URLSession:dataTask:didReceiveResponse:completionHandler:
    - (void)URLSession:dataTask:didReceiveData:
    //NSURLSessionDownloadDelegate
    - (void)URLSession:downloadTask:didFinishDownloadingToURL:
    - (void)URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
    - (void)URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:

3.NSURLSession断点续传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#import "ViewController.h"

@interface ViewController () <NSURLSessiondownloaddelegate,NSURLSessiondatadelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- (IBAction)download:(UIButton *)sender;
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
@property (nonatomic, strong) NSData *resumeData;
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation ViewController
//懒加载
- (NSURLSession *)session
{
if (!_session) {
// 获得session
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
- (IBAction)download:(UIButton *)sender {
// 按钮状态取反
sender.selected = !sender.isSelected;
if (self.task == nil) {
// 开始(继续)下载
if (self.resumeData) {
// 恢复
[self resume];
} else {
// 开始
[self start];
}
} else
{
// 暂停
[self pause];
}
}
/**
* 从零开始
*/

- (void)start
{
// 1.创建一个下载任务
NSURL *url = [NSURL URLWithString:@"http://192.168.1.110:8080/Server/resources"];
self.task = [self.session downloadTaskWithURL:url];
// 2.开始任务
[self.task resume];
}
/**
* 恢复(继续)
*/

- (void)resume
{
// 传入上次暂停下载返回的数据,就可以恢复下载
self.task = [self.session downloadTaskWithResumeData:self.resumeData];

// 开始任务
[self.task resume];

// 清空
self.resumeData = nil;
}
/**
* 暂停
*/

- (void)pause
{
__weak typeof(self) weakSelf = self;//弱引用,避免block内强引用循环
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
// resumeData : 包含了继续下载的开始位置\下载的url
weakSelf.resumeData = resumeData;
weakSelf.task = nil;
}];
}
#pragma mark - NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// response.suggestedFilename : 建议使用的文件名,一般跟服务器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];

// 将临时文件剪切或者复制Caches文件夹
NSFileManager *mgr = [NSFileManager defaultManager];

// AtPath : 剪切前的文件路径
// ToPath : 剪切后的文件路径
[mgr moveItemAtPath:location.path toPath:file error:nil];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"获得下载进度--%@", [NSThread currentThread]);
// 获得下载进度
self.progressView.progress = (double)totalBytesWritten / totalBytesExpectedToWrite;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
}