iOS 编程:NSURLSession

定义:描述 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。

网络请求创建流程

12345
graph LRNSURL-->NSURLRequestNSURLRequest-->NSURLSessionTaskNSURLSessionConfiguration-->NSURLSessionNSURLSession-->NSURLSessionTask

创建和配置 Session

一、NSURLSessionDataTask 示例

123456789101112131415161718192021222324252627282930313233
// 1.创建 NSURLSessionConfigurationNSURLSessionConfiguration *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.创建 NSURLSessionNSOperationQueue *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.创建 NSURLSessionDataTaskNSURL *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 示例

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
NSURL *url = [NSURL URLWithString:@"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf"];

// 1.创建 NSURLSessionConfigurationNSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.myapp.networking.background"];

// 2.创建 NSURLSessionNSOperationQueue *operationQueue = [NSOperationQueue mainQueue];

NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:operationQueue];

// 3.创建 NSURLSessionDownloadTaskNSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithURL:url];[downloadTask resume];

# prama mark - Delegate- (void)URLSession:(NSURLSession *)session      downloadTask:(NSURLSessionDownloadTask *)downloadTask      didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWrittentotalBytesExpectedToWrite:(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)fileOffsetexpectedTotalBytes:(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 *)downloadTaskdidFinishDownloadingToURL:(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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
// 1.创建 NSURLSessionConfigurationNSURLSessionConfiguration *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.创建 NSURLSessionNSOperationQueue *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.上传 StreamNSURL *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 请求

123456789101112131415161718
- (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 请求

12345678910111213141516171819202122232425
- (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 设置代理发送请求

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
- (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 *)dataTaskdidReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {    // 接收到服务器响应的时候调用    // 默认情况下不接收数据,必须告诉系统是否接收服务器返回的数据    completionHandler(NSURLSessionResponseAllow);}

- (void)URLSession:(NSURLSession *)session              task:(NSURLSessionTask *)taskdidCompleteWithError:(nullable NSError *)error {    // 请求失败调用}

- (void)URLSession:(NSURLSession *)session          dataTask:(NSURLSessionDataTask *)dataTask    didReceiveData:(NSData *)data {    // 接受到服务器返回数据的时候调用,可能被调用多次}

获取新闻示例代码:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
-(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];

}

参考

原文地址:https://www.cnblogs.com/lijianming180/p/12041520.html

时间: 2024-10-03 21:08:20

iOS 编程:NSURLSession的相关文章

ios编程之回调机制

ios编程之回调机制详解:   ———————————————— 函数/方法/block块一系列概念: 函数在大部分高级语言中都是个重要的概念,函数实现就是对一段代码的封装,我们一般会为了完成某一个业务功能或编程逻辑而需要组织数行代码,而这数行代码还有可能被使用多次,所以将它们封装成一个函数,每一次的执行我们称之为调函数或函数调用. 在C程序中,我们知道程序是从main函数开始执行,执行完main函数就退出程序,其实我们程序员很少去跟踪整个程序的执行流,一个程序(一段二进制代码)如何从加载到运行

0. iOS编程中启动画面的设置

这两天算是真郁闷,一个启动图片也要花一天的时间,虽然网上有介绍,也看了,可是就是不知道怎么处理,后来还是参考上一个程序的三张默认图片来设置的,320x480.png(Default.png),640x960.png([email protected]),640x1136.png([email protected]) iphone4/4s,iphone5/5s,iPad的三种尺寸.这三张图片本来是竖着放的,如果是横屏图像的话要按顺时针旋转90度来制作图片,(不知道是否还有更简便的方法,),把图片做

iOS编程开发笔记1——OOP,iOS,MVC

OOP,iOS,MVC 何政达 [前言]:写这篇文章的目的是总结一下这几天学到的有关iOS编程的有关知识点.主要分三部分:OOP的设计理念:iOS的构成:MVC的具体应用. Part I :OOP 说起OOP,大家都知道是什么--面向对象程序设计(Object-OrientedProgramming).但是我们为什么要使用这样的一种设计模式来进行我们的程序设计呢?记得一开始学习编程的时候是小学六年级,当时学习的是BASIC:上了初中以后学习PASCAL语言:上了高中开始学习C语言:到了大学之后逐

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

IOS编程教程(八):在你的应用程序添加启动画面 虽然你可能认为你需要编写闪屏的代码,苹果已经可以非常轻松地把它做在Xcode中.不需要任何编码.你只需要做的是设置一些配置. 什么是闪屏 对于那些新学代码的人,可能没有听说过“闪屏”把,让我先作一个简单的解释.闪屏是常见于iOS应用程序,以及其他桌面应用程序.这是你启动一个应用程序时,你看到的第一个画面.通常情况下,初始屏幕是一个覆盖整个屏幕的图像,消失后加载主屏幕.下图显示了几种闪屏: 简单闪屏(开始页面) 闪屏的主要目的是为了让用户知道你的程

iOS编程规范(整理)

一.文档结构管理 1.建立Libraries文件夹,所有第三方库放入其中. 2.建立Utilities文件夹,自已封装的类放入其中. 3.建立Constants.h头文件,所有的常量定义于其中.Constants.h文件放入Main文件组里面. 4.每个功能块放入一个Group,在目录里建立实际文件夹管理. 5.程序资源文件放入Supporting Files文件夹中.如.plist.数据库资料等. 6.在Supporting Files文件夹下建立Image.Music和Video等相关文件夹

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

iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) 很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化. 在iOS7以前是可以通过Mac地址来实现这个功能的,但是iOS7(包含)以后是无法获得Mac地址的:苹果官方推荐使用UUID,但是每次随着APP的卸载重装,UUID会随之发生变化,那该如何处理呢? 我们需要一个能在app卸载重装后不会改变的值,而keyChain恰巧就可以做到.配合UUID就可以实现了!让

[小白学iOS编程05]应用中常见的文件

注:[小白学iOS编程]是本小白根据某视频学习iOS编程过程的笔记记录,内容比较容易,高手勿喷. 转自请注明原博客地址:http://blog.csdn.net/fan_yufan/article/details/45955537 项目中常见的文件 1 Info.plist常见的设置 建立一个工程后,会在Supporting files文件夹下看到一个"工程名-Info.plist"的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 在旧版本Xcode创建的工程中,这个配置文件

IOS 编程中引用第三方的方类库的方法及常见问题

方法一:直接复制所有源文件到项目中 这种方法就是把第三方类库的所有源文件复制到项目中,直接把所有.h和.m文件拖到XCode项目中即可. 注意: 1. 如果第三方类库引用了一些系统自带类库,那么在项目中还需要额外引用那些类库. 2. 如果当前的项目启用了ARC,而引用的第三方类库未使用ARC,那还需要在项目信息的Targets – Build Parses 里找到第三方类库的.m文件,并为它们加上-fno-objc-arc标记. 3. 对于在未启用ARC的项目用引用使用了ARC的第三方类库,则需

iOS编程基础: Hello World App是如何运作的?

参照里Linux目录建立文件系统目录. 解压源码进入目录配置编译器和编译架构: CROSS_COMPILE ?= arm-linux- ARCH = arm. 执行make menuconfig 进行配置 选择静态编译, 在Installation Options中选择安装路径(可以直接选择刚才建立到目录).保存退出. make make install 生成文件. 进入建立好目录到etc目录执行:cp -rf ../../busybox-1.13.0/examples/bootfloppy/e