首页 iOS开发:NSURLSession详解
文章
取消

iOS开发:NSURLSession详解

在iOS开发中,网络请求是非常重要的一项功能。通过网络请求可以实现与服务器之间的数据交互,从而实现各种业务逻辑。NSURLSession是苹果官方提供的网络请求框架,自iOS7开始就被引入到了iOS SDK中。本文将会详细介绍NSURLSession的使用方法和实际应用场景,并对其内部实现细节进行分析。

NSURLSession简介

NSURLSession是基于HTTP/1.1协议的网络请求框架,同时也支持HTTPS、FTP等多种协议。它提供了一套完整的API,包括请求的创建、发送、响应处理和任务管理。NSURLSession可以帮助我们高效地完成网络请求的操作,并且可以通过配置不同的session,来满足各种请求场景下的需求。

一个NSURLSession可以包含多个NSURLSessionTask,每个NSURLSessionTask代表一个具体的网络请求任务。NSURLSessionTask可以是一个普通的GET/POST请求,也可以是一个文件下载任务或者一个文件上传任务等。NSURLSessionTask可以被取消、恢复以及挂起,并且可以获取网络请求的进度信息。

设计思路

NSURLSession 的内部实现基于 CFNetwork 框架,它是一个底层的网络协议栈,提供了对 TCP/IP、HTTP、FTP 和其他网络协议的支持。NSURLSession 在 CFNetwork 的基础上封装了更高层次的接口,使得开发者可以更方便地使用网络请求功能。

NSURLSession 采用了分层设计的思路,将网络请求过程拆分为多个阶段,每个阶段都由不同的模块负责。以下是一些核心模块的介绍:

  • NSURLSessionConfiguration:用于配置 NSURLSession 的行为,例如请求超时时间、缓存策略、身份验证方式等。
  • NSURLSessionTask:表示一个具体的网络请求任务,包含了请求的 URL、参数、请求头以及响应结果等信息。
  • NSURLSessionDelegate:定义了 NSURLSession 对象在不同事件发生时的回调方法,例如请求完成、请求失败、收到服务器响应等。
  • NSURLSessionDataDelegate:继承自 NSURLSessionDelegate,在数据传输过程中用于处理数据的回调,例如收到服务器返回的数据、上传进度变化等。

当我们创建一个 NSURLSession 对象并执行一个请求任务时,NSURLSession 会按照以下流程来处理请求:

  1. 根据 URLSessionConfiguration 创建一个 NSURLSession 实例。
  2. 调用 NSURLSession 实例的 dataTaskWithRequest 方法创建一个 NSURLSessionDataTask 对象。
  3. 将 NSURLSessionDataTask 对象交给 NSURLSession 来处理。
  4. 根据请求的 URL 和参数等信息构建一个请求报文,并通过底层的 CFNetwork 发送到服务器。
  5. 收到服务器响应后,NSURLSession 会将响应解析成一个 NSURLResponse 对象,并将其传递给 NSURLSessionDataTask。
  6. 如果该请求需要返回数据,则 NSURLSessionDataTask 会逐步收到服务器发来的数据,并将数据累加到一个 NSMutableData 对象中。
  7. 当所有数据都接收完成后,NSURLSessionDataTask 会调用 NSURLSessionDataDelegate 的代理方法,通知外部请求数据已经准备好了。
  8. 最终,请求结果会通过 NSURLSessionDataTask 的回调方法返回给上层应用。

NSURLSession API详解

NSURLSessionConfiguration

在使用NSURLSession之前,我们需要先创建一个NSURLSessionConfiguration对象,其中包含了网络请求的相关配置信息。NSURLSessionConfiguration中主要包含以下几个属性:

  • NSURLSessionConfiguration.defaultSessionConfiguration():默认的NSURLSessionConfiguration,与NSURLSession.sharedSession()相同。
  • NSURLSessionConfiguration.ephemeralSessionConfiguration():短暂的NSURLSessionConfiguration,不会将任何数据写到硬盘中,所有cookie、缓存等数据都只保存在内存中,并且当程序退出后就会被清空。
  • NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier::后台的NSURLSessionConfiguration,可以在应用退出或进入后台时仍然保持运行,并且可以在后台下载或上传数据。需要注意的是,后台NSURLSessionConfiguration有一些特殊的限制和注意事项,在具体使用时需要仔细阅读文档和API说明。

除了上述三种类型的NSURLSessionConfiguration以外,还可以通过NSURLSessionConfiguration的很多其他属性来对网络请求做更细致的配置,例如:

  • timeoutIntervalForRequest:请求超时时间。
  • allowsCellularAccess:是否允许使用蜂窝数据网络。
  • httpMaximumConnectionsPerHost:每个host最大并发请求数量。
  • HTTPAdditionalHeaders:附加的HTTP头信息。

NSURLSessionDataTask

NSURLSessionDataTask是NSURLSession最常用的任务类型,用于执行普通的GET或POST请求。创建一个NSURLSessionDataTask可以通过以下代码实现:

1
2
3
4
5
6
7
8
9
NSURL *url = [NSURL URLWithString:@"http://example.com"];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error == nil && data != nil) {
        // 请求成功,处理返回的数据
    } else {
        // 请求失败,处理错误信息
    }
}];
[task resume];

在上面的代码中,我们首先创建了一个NSURL对象表示请求的URL地址,然后通过NSURLSession的dataTaskWithURL:completionHandler:方法创建一个NSURLSessionDataTask对象。dataTaskWithURL:completionHandler:方法接收两个参数,第一个参数是NSURL对象,表示请求的URL地址;第二个参数是一个block,用于处理请求结果。在block中,我们可以通过检查NSError对象和NSData对象来判断请求是否成功,并进一步进行数据处理等操作。

NSURLSessionDownloadTask

NSURLSessionDownloadTask用于执行文件下载任务,可以自动将下载的数据存储到指定的文件路径中。创建一个NSURLSessionDownloadTask可以通过以下代码实现:

1
2
3
4
5
6
7
8
9
10
11
NSURL *url = [NSURL URLWithString:@"http://example.com/largefile.zip"];
NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error == nil && location != nil) {
        // 下载成功,将临时文件移动到指定的目标路径
        NSString *destinationPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/largefile.zip"];
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:destinationPath] error:nil];
    } else {
        // 下载失败,处理错误信息
    }
}];
[task resume];

在上面的代码中,我们首先创建了一个NSURL对象表示下载文件的URL地址,然后通过NSURLSession的downloadTaskWithURL:completionHandler:方法创建一个NSURLSessionDownloadTask对象。downloadTaskWithURL:completionHandler:方法接收两个参数,第一个参数是NSURL对象,表示请求的URL地址;第二个参数是一个block,用于处理请求结果。在block中,我们可以通过检查NSError对象和NSURL对象来判断下载是否成功,并进一步进行数据处理等操作。

NSURLSessionUploadTask

NSURLSessionUploadTask用于执行文件上传任务,可以自动将上传的数据发送到服务器端。创建一个NSURLSessionUploadTask可以通过以下代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
NSURL *url = [NSURL URLWithString:@"http://example.com/upload.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";

NSURL *fileURL = [NSURL fileURLWithPath:@"/path/to/your/file"];
NSURLSessionUploadTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromFile:fileURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (error == nil && data != nil) {
        // 上传成功,处理返回的数据
    } else {
        // 上传失败,处理错误信息
    }
}];
[task resume];

在上面的代码中,我们首先创建了一个NSURL对象表示上传文件的URL地址,然后通过NSMutableURLRequest对象创建一个HTTP POST请求。接着,我们使用NSURLSession的uploadTaskWithRequest:fromFile:completionHandler:方法创建一个NSURLSessionUploadTask对象,该方法接收三个参数:第一个参数是NSURLRequest对象,表示请求的内容;第二个参数是NSURL对象,表示上传的文件路径;第三个参数是一个block,用于处理请求结果。

NSURLSessionDelegate

NSURLSessionDelegate是NSURLSession的代理协议,可用于处理网络请求的各种事件,例如请求完成、请求失败、认证挑战等。需要注意的是,NSURLSessionDelegate中的很多方法都是可选的,因此我们可以根据需要选择需要实现的方法。下面是NSURLSessionDelegate中常用的一些方法:

  • URLSession:didBecomeInvalidWithError::当NSURLSession失效的时候调用,如果失效是由于错误引起的,那么error参数就不为空。
  • URLSession:didReceiveChallenge:completionHandler::当NSURLSession进行身份验证或服务器端证书验证时调用,我们可以在这个方法中实现自定义的验证逻辑。
  • URLSession:dataTask:didReceiveResponse:completionHandler::当NSURLSessionDataTask接收到服务器端的响应时调用,我们可以在这个方法中获取响应的状态码和头信息等。
  • URLSession:dataTask:didReceiveData::当NSURLSessionDataTask接收到一部分数据时调用,我们可以在这个方法中对数据进行处理。
  • URLSessionTask:didCompleteWithError::当NSURLSessionTask完成时调用,我们可以在这个方法中处理错误信息或者处理请求结果。
本文由作者按照 CC BY 4.0 进行授权