定义:描述 Foundation 框架类在标准的网络传输协议下,用 URLs 连接因特网并与服务器交互的一整套体系。

支持的传输协议:

  • File Transfer Protocol (ftp://)
  • Hypertext Transfer Protocol (http://)
  • Hypertext Transfer Protocol with encryption (https://)
  • Local file URLs (file:///)
  • Data URLs (data://)

结构图

网络系统模块

5个模块:代理支持、身份验证和凭据、cookie 存储、配置管理和缓存管理。

Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。

NSURLSessionTask

NSURLSessionDelegate 委托协议

Session 会话的概念

Session中任务的行为取决于三个方面:

  1. Session 的类型(取决于创建的配置对象类型);
  2. task 任务的类型;
  3. task 任务被创建时,app 是否处于前台状态?

Session 的类型

  • 默认会话(Default session):与其他用于下载URL的 Foundation 方法类似。 使用永久性的基于磁盘的缓存并将凭据存储在用户的钥匙串中。
  • 短暂会话(Ephemeral session):不会将任何数据存储到磁盘; 所有缓存,凭证等都保存在 RAM 中并与会话相关联。 因此,当应用程序使会话无效时,会自动清除该会话。
  • 后台会话(Background session):类似于默认会话,但是会使用单独的进程处理所有数据传输。 后台会话有一些额外的限制。

⚠️ NSURLSession 使用完需要释放,否则会引起内存泄漏问题。

task 任务类型

NSURLSession 支持三种类型的任务:data tasks, download tasks 和 upload tasks。

  • data tasks:使用 NSData 对象发送和接收数据。 处理应用程序与服务器之间的简短的,经常交互的请求。 数据任务可以在每次接收到数据后就返回,或者通过 completion handler 一次性返回所有数据到您的应用程序。
  • download tasks:下载任务以文件的形式检索数据,并在应用程序未运行时支持后台下载。
  • upload tasks:上传任务以文件的形式发送数据,并在应用程序未运行时支持后台上传。

后台传输注意事项

NSURLSession 类在您的应用程序被暂停时支持后台传输。 后台传输仅由使用后台会话配置对象(调用 backgroundSessionConfiguration :返回的会话)提供。

  • 必须提供委托对象来进行事件传递。 (对于上传和下载任务,代理的行为与在进程内传输相同。)
  • 只支持HTTP和HTTPS协议(没有自定义协议)。
  • 始终遵循重定向。
  • 只支持 file 文件上传(应用程序退出后,data 或 stream 类型的传输将会失败)。
  • 如果在应用程序处于后台时启动后台传输,配置对象的 discretionary 属性将被视为true。

网络请求创建流程

1
2
3
4
5
graph LR
NSURL-->NSURLRequest
NSURLRequest-->NSURLSessionTask
NSURLSessionConfiguration-->NSURLSession
NSURLSession-->NSURLSessionTask

创建和配置 Session

一、NSURLSessionDataTask 示例

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
// 1.创建 NSURLSessionConfiguration
NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSessionConfiguration *ephemeralConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.myapp.networking.background"]; // 配置默认会话的缓存行为
NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *cachePath = [cachesDirectory stringByAppendingPathComponent:@"MyCache"]; /* Note:
iOS需要设置相对路径:〜/Library/Caches
OS X 要设置绝对路径。
*/
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:16384
diskCapacity:268435456
diskPath:cachePath];
defaultConfiguration.URLCache = cache;
defaultConfiguration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; // 2.创建 NSURLSession
NSOperationQueue *operationQueue = [NSOperationQueue mainQueue]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfiguration delegate:self delegateQueue:operationQueue];
NSURLSession *ephemeralSession = [NSURLSession sessionWithConfiguration:ephemeralConfiguration delegate:self delegateQueue:operationQueue];
NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:operationQueue]; // 3.创建 NSURLSessionDataTask
NSURL *url = [NSURL URLWithString:@"https://www.example.com/"]; [[defaultSession dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"Got response %@ with error %@.n", response, error);
NSLog(@"DATA:n%@nEND DATAn", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}] resume];

二、NSURLSessionDownloadTask 示例

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
NSURL *url = [NSURL URLWithString:@"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf"];

// 1.创建 NSURLSessionConfiguration
NSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.myapp.networking.background"]; // 2.创建 NSURLSession
NSOperationQueue *operationQueue = [NSOperationQueue mainQueue]; NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:operationQueue]; // 3.创建 NSURLSessionDownloadTask
NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithURL:url];
[downloadTask resume]; # prama mark - Delegate
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"Session %@ download task %@ wrote an additional %lld bytes (total %lld bytes) out of an expected %lld bytes.n", session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
} - (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
NSLog(@"Session %@ download task %@ resumed at offset %lld bytes out of an expected %lld bytes.n", session, downloadTask, fileOffset, expectedTotalBytes);
} - (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"Session %@ download task %@ finished downloading to URL %@n", session, downloadTask, location); // Perform the completion handler for the current session
self.completionHandlers[session.configuration.identifier](); // Open the downloaded file for reading
NSError *readError = nil;
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:location error:readError];
// ... // Move the file to a new URL
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *cacheDirectory = [[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] firstObject];
NSError *moveError = nil;
if ([fileManager moveItemAtURL:location toURL:cacheDirectory error:moveError]) {
// ...
}
}

三、Uploading Body Content

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
// 1.创建 NSURLSessionConfiguration
NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; // 配置默认会话的缓存行为
NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *cachePath = [cachesDirectory stringByAppendingPathComponent:@"MyCache"]; /* Note:
iOS需要设置相对路径:〜/Library/Caches
OS X 要设置绝对路径。
*/
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:16384
diskCapacity:268435456
diskPath:cachePath];
defaultConfiguration.URLCache = cache;
defaultConfiguration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; // 2.创建 NSURLSession
NSOperationQueue *operationQueue = [NSOperationQueue mainQueue]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfiguration delegate:self delegateQueue:operationQueue]; // ***************************************************************
// 3.1.上传 Data
NSURL *textFileURL = [NSURL fileURLWithPath:@"/path/to/file.txt"];
NSData *data = [NSData dataWithContentsOfURL:textFileURL]; NSURL *url = [NSURL URLWithString:@"https://www.example.com/"];
NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:url];
mutableRequest.HTTPMethod = @"POST";
[mutableRequest setValue:[NSString stringWithFormat:@"%lld", data.length] forHTTPHeaderField:@"Content-Length"];
[mutableRequest setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"]; NSURLSessionUploadTask *uploadTask = [defaultSession uploadTaskWithRequest:mutableRequest fromData:data];
[uploadTask resume]; // ***************************************************************
// 3.2.上传 File
NSURL *textFileURL = [NSURL fileURLWithPath:@"/path/to/file.txt"]; NSURL *url = [NSURL URLWithString:@"https://www.example.com/"];
NSMutableURLRequest *mutabl 大专栏  iOS 编程:NSURLSessioneRequest = [NSMutableURLRequest requestWithURL:url];
mutableRequest.HTTPMethod = @"POST"; NSURLSessionUploadTask *uploadTask = [defaultSession uploadTaskWithRequest:mutableRequest fromFile:textFileURL];
[uploadTask resume]; // ***************************************************************
// 3.3.上传 Stream
NSURL *textFileURL = [NSURL fileURLWithPath:@"/path/to/file.txt"]; NSURL *url = [NSURL URLWithString:@"https://www.example.com/"];
NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:url];
mutableRequest.HTTPMethod = @"POST";
mutableRequest.HTTPBodyStream = [NSInputStream inputStreamWithFileAtPath:textFileURL.path];
[mutableRequest setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
[mutableRequest setValue:[NSString stringWithFormat:@"%lld", data.length] forHTTPHeaderField:@"Content-Length"]; NSURLSessionUploadTask *uploadTask = [defaultSession uploadTaskWithStreamedRequest:mutableRequest];
[uploadTask resume];

四、NSURLSessionDataTask 发送 GET 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)p_NSURLSessionDataTask_GET {
// 请求路径
NSURL *url = [NSURL URLWithString:@"https://op.juhe.cn/shanghai/hospital?dtype=&key=123"]; // 1.创建 NSURLSession,使用共享 Session
NSURLSession *session = [NSURLSession sharedSession]; // 2.创建 NSURLSessionDataTask, 默认 GET 请求
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"%@",error.localizedDescription);
}else {
NSLog(@"%@",data);
}
}];
// 3.执行 Task
[dataTask resume];
}

五、NSURLSessionDataTask 发送 POST 请求

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
- (void)p_NSURLSessionDataTask_POST {
// 请求路径
NSURL *url = [NSURL URLWithString:@"https://op.juhe.cn/shanghai/hospital"]; // 创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 设置请求方法
request.HTTPMethod = @"POST";
// 设置请求体
NSString *stringBody = @"dtype=&key=123";
request.HTTPBody = [stringBody dataUsingEncoding:NSUTF8StringEncoding]; // 1.创建 NSURLSession,使用共享 Session
NSURLSession *session = [NSURLSession sharedSession];
// 2.创建 NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
// error
}else {
// data
}
}];
// 3.执行 Task
[dataTask resume];
}

六、NSURLSessionDataTask 设置代理发送请求

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
- (void)p_NSURLSessionDataTask_Delegate {
// 请求路径
NSURL *url = [NSURL URLWithString:@"https://op.juhe.cn/shanghai/hospital"]; // 创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 设置请求方法
request.HTTPMethod = @"POST";
// 设置请求体
NSString *stringBody = @"dtype=&key=5718abc3837ecb471c5d5b1ef1e35130";
request.HTTPBody = [stringBody dataUsingEncoding:NSUTF8StringEncoding]; // 1.创建 NSURLSessionConfiguration
NSURLSessionConfiguration *configuration =
[NSURLSessionConfiguration defaultSessionConfiguration];
// 2.创建 NSURLSession
NSURLSession *session =
[NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:nil];
// 3.创建 NSURLSessionDataTask
NSURLSessionDataTask *dataTask =
[session dataTaskWithRequest:request];
// 4.执行 Task
[dataTask resume];
} #pragma mark - NSURLSessionDelegate - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error {
// 请求失败调用。
} - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
// 处理身份验证和凭据。
} - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
// 后台任务下载完成后调用
} #pragma mark - NSURLSessionDataDelegate - (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
// 接收到服务器响应的时候调用
// 默认情况下不接收数据,必须告诉系统是否接收服务器返回的数据
completionHandler(NSURLSessionResponseAllow);
} - (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error {
// 请求失败调用
} - (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
// 接受到服务器返回数据的时候调用,可能被调用多次
}

获取新闻示例代码:

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
-(void)viewdidload {

    //创建NSURLSession对象
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
//发起网络请求获取新闻
[self fetchHrssnews];
} #pragma 获取新闻方法
- (void)fetchHrssnews { //创建NSURLRequest对象
NSString *requestString = hrssnewsString;
NSURL *url = [NSURL URLWithString:requestString];
//方法参数:统一资源定位符、缓存策略:忽略本地缓存、等待web服务器响应最长时间
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0f];
//设置请求方式为POST
[req setHTTPMethod: @"POST"]; //设置请求体
NSString *dataString = @"ksym=0&jsym=15";
NSData *postData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
[req setHTTPBody:postData]; //创建NSURLSessionDataTask对象
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //解析JSON数据
NSDictionary *jsonObject = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:nil]; self.msgflag = jsonObject[@"msgflag"];
HQLog(@"msgflag:%@",self.msgflag);
self.msg = jsonObject[@"msg"];
HQLog(@"msg:%@",self.msg); //判断是否成功获取服务器端数据
if ([self.msgflag isEqualToString:@"0"]) {
HQLog(@"msgflag:%@",self.msgflag);
}else{
HQLog(@"msgflag:-1,msg:For input string: ");
} //使用dispatch_asynch函数让reloadData方法在主线程中运行
dispatch_async(dispatch_get_main_queue(), ^{
//重新加载UITableView对象的数据
[self.tableView reloadData];});
//停止刷新
[self.tableView.mj_header endRefreshing];
}]; //NSURLSessionDataTask在刚创建的时候默认处于挂起状态,需要手动调用恢复。
[dataTask resume]; }

参考

iOS 编程:NSURLSession的更多相关文章

  1. [译] 二、开始iOS编程之前,你还需要做什么?

    声明:本文翻译自AppCoda网站的文章:What You Need to Begin iOS Programming?,作者是创建者Simon Ng.如有异议,请联系博主.   更新:帖子已经重新被 ...

  2. IOS编程User Interface基础

    IOS编程之User Interface基础 目录 概述 相关概念 常见问题 状态栏的隐藏 应用图标的设置 概述 IOS用户界面是APP呈现给用户最直观.最常用的方式,因此学会用户界面的编程是学习IO ...

  3. IOS编程之多线程

    IOS编程之多线程 目录 概述——对多线程的理解 IOS中实现多线程的三种方式 NSThread 线程创建 线程的同步与锁 线程间的交互 线程的操作方法 NSOperation and NSOpera ...

  4. iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)

    iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) 很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化. 在iO ...

  5. IOS编程教程(八):在你的应用程序添加启动画面

    IOS编程教程(八):在你的应用程序添加启动画面   虽然你可能认为你需要编写闪屏的代码,苹果已经可以非常轻松地把它做在Xcode中.不需要任何编码.你只需要做的是设置一些配置. 什么是闪屏 对于那些 ...

  6. iOS编程之前

    iOS编程之前 更新:帖子已经重新被更新过,以便能更好的兼容Xcode 5和iOS 7.       至今为止,已经超过6000位读者加入了这个iOS免费教程.首先,我要感谢这些加入我们社区的朋友.在 ...

  7. iOS编程中比较两个日期的大小

    转自:http://www.myext.cn/other/a_30922.html 比较日期大小是任何编程语言都会经常遇到的问题,再iOS编程中,通常用NSDate对象来存储一个时间(包括日期和时间. ...

  8. 新书《iOS编程(第6版)》抢鲜试读

    我最近翻译了Big Nerd Ranch的<iOS编程(第6版)>.我用了大半年时间,尽可能做到通顺易懂.不足之处请大家多多指正.感谢辛苦审校的丁道骏同学. 这本书得过Jolt大奖,原书在 ...

  9. iOS - 网络 - NSURLSession

    1.NSURLSession基础 NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS,所以也可以使用.NSURLCon ...

随机推荐

  1. win10环境下pycharm成功安装torch,解决报错:from torch._C import * ImportError: DLL load failed: 找不到指定的模块

    https://blog.csdn.net/watermelon12138/article/details/97624733

  2. 量化投资_关于Multicharts砖型图(传统砖型图和非传统砖型图)最详细的解释_调用篇

    1. 砖图形成数组后,我们再对他们复制到数组中然后再调用出来看一下. 2. 如下是累计只取20个数组大小为例,如果开始阶段数组长度组成初始的Array[20]的长度,然后这个数组的最后一个值填满后,进 ...

  3. Matlab高级教程_第四篇:Matlab高级函数_关键词:drawnow,addpoints,animatedline,getpoints

    0. MATLAB真实航母基本的工具,其中的函数/工具不计其数,而且有些函数/工具非常的炫酷.在MATLAB第四篇章把平时工作中用到的些许函数进行使用的讲解 主题1.:drawnow 解释:更新图窗并 ...

  4. Java创建文件夹、创建文件、上传文件,下载文件

    1.创建文件夹 /** * 判断文件夹是否存在 * @param myPath */ public static void judeDirExists(File myPath) { if (!myPa ...

  5. Hive(二)—— 架构设计

    Hive架构 Figure 1 also shows how a typical query flows through the system. 图一显示一个普通的查询是如何流经Hive系统的. Th ...

  6. 搭建WordPress个人博客

    1. 准备LNMP环境 LNMP 是 Linux.Nginx.MySQL 和 PHP 的缩写,是 WordPress 博客系统依赖的基础运行环境.我们先来准备 LNMP 环境 安装Nginx 使用 y ...

  7. IPC之——信号量集(多个信号量)

    如果两个进程不仅需要同步,还要保证先后执行顺序,就要用两个信号量(互斥锁)来解决 //栅栏模型:实现以下框架中的四个子进程 所有进程做完任务后 在一起执行下一次  #include <stdio ...

  8. ui-choose|列表选择jQuery美化插件

    ui-choose是一款基于jQuery的列表选择美化插件.ui-choose可用于选项不太多的select.radio.checkbox等,提升用户体验. 使用方法 使用ui-choose列表美化插 ...

  9. MySQL数据库优化、设计与高级应用

    MySQL数据库优化主要涉及两个方面,一方面是对SQL语句优化,另一方面是对数据库服务器和数据库配置的优化. 数据库优化 SQL语句优化 为了更好的看到SQL语句执行效率的差异,建议创建几个结构复杂的 ...

  10. SpringBoot开发二十-Redis入门以及Spring整合Redis

    安装 Redis,熟悉 Redis 的命令以及整合Redis,在Spring 中使用Redis. 代码实现 Redis 内置了 16 个库,索引是 0-15 ,默认选择第 0 个 Redis 的常用命 ...