前言
本篇文章来介绍一下 NSURLSession 。
之前的网络基础架构NSURLConnection,被苹果在iOS9之后宣布弃用,在2013年的WWDC上,Apple揭开了NSURLConnection继任者的面纱:NSURLSession。
NSURLSession 介绍
-
NSURLSession 支持 http2.0 协议。
-
与NSURLConnection相比,NSURLSession最直接的改善就是提供了配置每个会话的缓存,协议,cookie和证书政策(credential policies)。这使得框架的网络基础架构和部分应用程序独立工作,而不会互相干扰。每一个NSURLSession对象都是根据一个NSURLSessionConfiguration初始化的,该NSURLSessionConfiguration指定了上面提到的政策,以及一系列为了提高移动设备性能而专门添加的新选项。
-
NSURLSession针对下载/上传等复杂的网络操作提供了专门的解决方案,针对普通、上传和下载分别对应三种不同的网络请求任务:NSURLSessionDataTask, NSURLSessionUploadTask和NSURLSessionDownloadTask。创建的task都是挂起状态,需要调用resume方法才能执行。
NSURLSessionTask.png
NSURLSessionDataTask,可以用来处理一般的网络请求,如 GET | POST 请求等。
NSURLSessionDataTask 有一个子类为 NSURLSessionUploadTask,主要用于处理上传请求。
NSURLSessionDownloadTask,主要用于处理下载请求。
NSURLSession 使用
NSURLSessionDataTask 发送 GET 请求
//请求链接
NSString * urlStr = @"https://api.douban.com/v2/book/1220562";
//创建 NSURLSession 对象
NSURLSession * session = [NSURLSession sharedSession];
/**
创建 Data Task 请求
completionHandler 完成之后的回调(成功或失败)
@param data 返回的数据(响应体)
@param response 响应头
@param error 错误信息
*/
NSURLSessionDataTask * dataTask = [session dataTaskWithURL:[NSURL URLWithString:urlStr] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary * dataDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"--- %@ %@ %@", dataDict, NSStringFromClass([response class]), error);
}];
//执行data task
[dataTask resume];
NSURLSessionDataTask 发送 POST 请求
NSURLSession * session = [NSURLSession sharedSession];
NSString * urlStr = @"https://api.weibo.com/2/statuses/update.json";
//创建可变请求对象
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
//设置请求类型 post
request.HTTPMethod = @"POST";
//设置请求体
request.HTTPBody = [@"status=123&access_token=123" dataUsingEncoding:NSUTF8StringEncoding];
//创建请求 task
NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析返回数据
NSDictionary * dataDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"--- %@ %@ %@", dataDict, NSStringFromClass([response class]), error);
}];
//执行data task
[dataTask resume];
NSURLSessionDownloadTask 下载内容
//下面的例子,使用NSURLSessionDownloadTask来下载一张图片
NSURLSession * session = [NSURLSession sharedSession];
//图片链接
NSString * urlStr = @"https://img.haomeiwen.com/i288548/8240c430a7526d6a.png";
NSURLSessionDownloadTask * downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:urlStr] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//下载完成,下载的内容是先保存在沙盒的Tmp文件夹中,location文件保存的路径
//在tmp文件中只是短暂的保存,很快就会被清除
//要想保存下来,可以移动到别的文件夹中,下面是将文件保存到Caches文件夹中
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
}];
[downloadTask resume];
使用代理方法获取数据
//创建获取数据任务,用来获取图片数据
NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.myapp.networking.getdata"];
NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
//图片链接
NSString * urlStr = @"http://f.hiphotos.baidu.com/image/pic/item/1f178a82b9014a903ba25d77a0773912b21bee58.jpg";
NSURLSessionDataTask * dataTask = [session dataTaskWithURL:[NSURL URLWithString:urlStr]];
[dataTask resume];
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask
didReceiveResponse:(nonnull NSURLResponse *)response
completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
//开始接收数据
self.dataM = [NSMutableData data];
//必须告诉系统是否接收服务器返回的数据
completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
//拼接服务器返回的数据
[self.dataM appendData:data];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
//获取到全部数据
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = [UIImage imageWithData:self.dataM];
});
}
下载任务NSURLSessionDownloadTask,代理方法 NSURLSessionDownloadDelegate
NSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.myapp.networking.background"];
NSOperationQueue *operationQueue = [NSOperationQueue mainQueue];
NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfiguration delegate:self delegateQueue:operationQueue];
NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/1f178a82b9014a903ba25d77a0773912b21bee58.jpg"];
NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithURL:url];
[downloadTask resume];
//代理方法
- (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]) {
// ...
}
}
Reference
https://developer.apple.com/documentation/foundation/urlsession
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html#//apple_ref/doc/uid/10000165i
网友评论