定义:描述 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中任务的行为取决于三个方面:
- Session 的类型(取决于创建的配置对象类型);
- task 任务的类型;
- 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编程之前,你还需要做什么?
声明:本文翻译自AppCoda网站的文章:What You Need to Begin iOS Programming?,作者是创建者Simon Ng.如有异议,请联系博主. 更新:帖子已经重新被 ...
- IOS编程User Interface基础
IOS编程之User Interface基础 目录 概述 相关概念 常见问题 状态栏的隐藏 应用图标的设置 概述 IOS用户界面是APP呈现给用户最直观.最常用的方式,因此学会用户界面的编程是学习IO ...
- IOS编程之多线程
IOS编程之多线程 目录 概述——对多线程的理解 IOS中实现多线程的三种方式 NSThread 线程创建 线程的同步与锁 线程间的交互 线程的操作方法 NSOperation and NSOpera ...
- iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)
iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) 很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化. 在iO ...
- IOS编程教程(八):在你的应用程序添加启动画面
IOS编程教程(八):在你的应用程序添加启动画面 虽然你可能认为你需要编写闪屏的代码,苹果已经可以非常轻松地把它做在Xcode中.不需要任何编码.你只需要做的是设置一些配置. 什么是闪屏 对于那些 ...
- iOS编程之前
iOS编程之前 更新:帖子已经重新被更新过,以便能更好的兼容Xcode 5和iOS 7. 至今为止,已经超过6000位读者加入了这个iOS免费教程.首先,我要感谢这些加入我们社区的朋友.在 ...
- iOS编程中比较两个日期的大小
转自:http://www.myext.cn/other/a_30922.html 比较日期大小是任何编程语言都会经常遇到的问题,再iOS编程中,通常用NSDate对象来存储一个时间(包括日期和时间. ...
- 新书《iOS编程(第6版)》抢鲜试读
我最近翻译了Big Nerd Ranch的<iOS编程(第6版)>.我用了大半年时间,尽可能做到通顺易懂.不足之处请大家多多指正.感谢辛苦审校的丁道骏同学. 这本书得过Jolt大奖,原书在 ...
- iOS - 网络 - NSURLSession
1.NSURLSession基础 NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS,所以也可以使用.NSURLCon ...
随机推荐
- Go-简介-发展
01-Go语言介绍 目录 Go语言介绍 Go语言特性 Go语言发展(版本/特性) Go语言应用 谁在用 应用领域 Go语言项目 Go语架构 Go语言发展前景 Go语言介绍 Go 即Golang,是Go ...
- 关于redis的使用总结
简介 redis是一个开源的用c语言编写的数据库,但并不像常规的关系型数据库那样把数据存储在表中 , 而是像Java中的Map集合一样,存储的是一系列key=value键值对,redis属于NoSQL ...
- 是时候写个自己的dialog了
组件下载地址:http://pan.baidu.com/s/1pJFVfej 最近做的项目需要用到对话框,但是原生的弹出框你是知道的.如果有时间,还是自己尝试一下,也是可以的. 一个简单图 里面的输入 ...
- Python3.7离线安装Requests无法正常使用问题
继续搬砖...... 春节前,克服了网络受限的情况下离线安装Python库文件问题,传送门如下: https://www.cnblogs.com/mrgavin/p/12202214.html htt ...
- 数学之美_正态分布(Python代码)
1 在概率统计中,我们针对某个事件当中各个样本发生的概率的频率进行统计,用一个函数的形式写出的这个概率的频率函数就叫做分布函数. 2 分布函数顾名思义,就是某个连续事件发生频率的汇总表示.再直白一点儿 ...
- 数据处理——One-Hot Encoding
一.One-Hot Encoding One-Hot编码,又称为一位有效编码,主要是采用位状态寄存器来对个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效. 在实 ...
- iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码
iOS精选源码 如丝般顺滑的微信朋友圈(点赞,评论,图文混排表情,... 动态菜单第三版本:动态项,自适应方向 仿appstore首页滚动效果 iOS 透明导航栏方案 TransparentNavig ...
- coursera课程视频
#!/usr/bin/env python # coding=utf-8 import urllib import urllib2 import cookielib def setcookie(ena ...
- Django路由层与视图层
表与表之间建关系 图书管理系统为例 书籍表 出版社表 作者表 三个表之间的关系: 考虑表之间的关系:换位思考 1.书籍和出版社是一对多,外键字段建立在书籍表中 2.书籍和作者是多对多, 需要建立第三方 ...
- Ansible--初始ansible
一.ansible简介 ansible是一种自动化运维工具.实现批量操作系统配置.批量程序部署.批量命令运行等功能. ansible工作在agentless模式下,并且具有幂等性(幂等性不会重复执行相 ...