tipsiOS Networkios网络

NSURLSession的了解

2016-01-20  本文已影响2618人  付寒宇

在苹果彻底弃用NSURLConnection之后自己总结的一个网上的内容,加上自己写的小Demo,很多都是借鉴网络上的资源,有需要的朋友可以看看。
排版之前也是乱弄的(因为之前就自己看么囧)
可以看Demo下的pdf
Demo地址:https://github.com/Fuhanyu/FHYNSURLSessionDemo

一.引言:

由于Xcode 7中,NSURLConnection的API已经正式被苹果弃用。虽然该API将继续运行,但将没有新功能将被添加,并且苹果已经通知所有基于网络的功能,以充分使NSURLSession向前发展。

二.快速了解与改变AFNetworking篇:

AFNetworking是一款在OS X和iOS下都令人喜爱的网络库,为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。如果你的项目以前使用过这些API,建议您立即升级到基于 NSURLSession 的API的AFNetworking的版本。

AFNetworking 1.0建立在NSURLConnection的基础API之上 ,AFNetworking 2.0开始使用NSURLConnection的基础API ,以及较新基于NSURLSession的API的选项。 AFNetworking 3.0现已完全基于NSURLSession的API,这降低了维护的负担,同时支持苹果增强关于NSURLSession提供的任何额外功能。

1.弃用的类

下面的类已从AFNetworking 3.0中废弃:

2.让我们看一下原来封装的简单网络处理类

//创建一个HTTP请求操作管理对象
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//通过设置responseSerializer,自动完成返回数据的解析,直接获取json格式的responseObject。
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json", @"text/plain", @"text/html", nil];

//允许无效的 SSL 证书:
//NSURLConnection已经封装了https连接的建立、数据的加密解密功能,我们直接使用NSURLConnection是可以访问https网站的,但NSURLConnection并没有验证证书是否合法,无法避免中间人攻击。要做到真正安全通讯,需要我们手动去验证服务端返回的证书,AFSecurityPolicy封装了证书验证的过程,让用户可以轻易使用,除了去系统信任CA机构列表验证,还支持SSL Pinning方式的验证。
manager.securityPolicy.allowInvalidCertificates = YES;//生产环境不建议使用

[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"%@",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];

3.AFHTTPRequestOperationManager 核心代码

如果你以前使用 AFHTTPRequestOperationManager , 你将需要迁移去使用AFHTTPSessionManager。 以下的类在两者过渡间并没有变化:

AFNetworking 2.x

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"请求的url" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"成功");
} failure:^(AFHTTPRequestOperation operation, NSErrorerror) {
NSLog(@"失败");
}];

AFNetworking 3.0
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
[session GET:@"请求的url" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"成功");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"失败");
}];

三.基本了解NSURLSession

NSURLSessionTask

NSURLsessionTask 是一个抽象类,其下有 3 个实体子类可以直接使用:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。这 3 个子类封装了现代程序三个最基本的网络任务:获取数据,比如 JSON 或者 XML,上传文件和下载文件。

当一个 NSURLSessionDataTask 完成时,它会带有相关联的数据,而一个 NSURLSessionDownloadTask 任务结束时,它会带回已下载文件的一个临时的文件路径。因为一般来说,服务端对于一个上传任务的响应也会有相关数据返回,所以NSURLSessionUploadTask 继承自 NSURLSessionDataTask。

所有的 task 都是可以取消,暂停或者恢复的。当一个 download task 取消时,可以通过选项来创建一个恢复数据(resume data),然后可以传递给下一次新创建的 download task,以便继续之前的下载。

1⃣️NSURLSessionDataTask

2.GET请求

//1.创建NSURLSession对象(可以获取单例对象)
NSURLSession *session = [NSURLSession sharedSession];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.liwushuo.com/v2/banners?channel=iOS"]];
//2.根据NSURLSession对象创建一个Task
/*
 注意:该block是在子线程中调用的,如果拿到数据之后要做一些UI刷新操作,那么需要回到主线程刷新
 第一个参数:需要发送的请求对象
 block:当请求结束拿到服务器响应的数据时调用block
 block-NSData:该请求的响应体
 block-NSURLResponse:存放本次请求的响应信息,响应头,真实类型为NSHTTPURLResponse
 block-NSErroe:请求错误信息
 */
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    //拿到响应头信息
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //4.解析拿到的响应数据
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@ \n %@", dic, res.allHeaderFields);
}];
//3.执行Task
//注意:刚创建出来的task默认是挂起状态的,需要调用该方法来启动任务(执行任务
[dataTask resume];

3.第二种GET请求

//1.创建NSURLSession对象(可以获取单例对象)
NSURLSession session = [NSURLSession sharedSession];
//2.创建一个Task
//注意:该方法内部默认会把URL对象包装成一个NSURLRequest对象(默认是GET请求)
//方法参数说明
/

//第一个参数:发送请求的URL地址
//block:当请求结束拿到服务器响应的数据时调用block
//block-NSData:该请求的响应体
//block-NSURLResponse:存放本次请求的响应信息,响应头,真实类型为NSHTTPURLResponse
//block-NSErroe:请求错误信息
*/
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://api.liwushuo.com/v2/banners?channel=iOS"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//拿到响应头信息
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //4.解析拿到的响应数据
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@ \n %@", dic, res.allHeaderFields);
}];

[dataTask resume];

4.POST请求

 //1.创建NSURLSession对象(可以获取单例对象)
NSURLSession *session = [NSURLSession sharedSession];

//2.根据NSURLSession对象创建一个Task

NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];

//创建一个请求对象,并这是请求方法为POST,把参数放在请求体中传递
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
    //拿到响应头信息
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //解析拿到的响应数据
    NSLog(@"%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
}];

//3.执行Task
//注意:刚创建出来的task默认是挂起状态的,需要调用该方法来启动任务(执行任务)
[dataTask resume];

2⃣️NSURLSessionDownloadTask

1.使用NSURLSession和NSURLSessionDownload可以很方便的实现文件下载操作

//
// NSURLSessionNetWork.m
// FHYNetworkHandle
//
// Created by 付寒宇 on 15/11/7.
// Copyright © 2015年 付寒宇. All rights reserved.
//

import "NSURLSessionDownloadTaskShow.h"

@interface NSURLSessionDownloadTaskShow ()<NSURLSessionDownloadDelegate>
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutlet UIProgressView *progressBar;
@property (strong, nonatomic) IBOutlet UIButton *start;
@property (strong, nonatomic) IBOutlet UIButton *pause;
@property (strong, nonatomic) IBOutlet UIButton *resume;
@property (atomic, strong) NSURLSessionDownloadTask *task;
@property (atomic, strong) NSData *partialData;

@end

@implementation NSURLSessionDownloadTaskShow

//创建Session对象

}

pragma mark NSURLSessionDownloadDelegate

//完成下载任务 保存

//返回下载进度代理方法
/*
当接收到下载数据的时候调用,可以在该方法中监听文件下载的进度
该方法会被调用多次
totalBytesWritten:已经写入到文件中的数据大小
totalBytesExpectedToWrite:目前文件的总大小
bytesWritten:本次下载的文件数据大小
*/

//创建文件本地保存目录
-(NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *documentsDirectory = urls[0];
return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];
}
//把文件拷贝到指定路径
-(BOOL) copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination
{

NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:destination error:NULL];
[fileManager copyItemAtURL:location toURL:destination error:&error];
if (error == nil) {
    return true;
}else{
    NSLog(@"%@",error);
    return false;
}

}

@end

2.downloadTaskWithURL内部默认已经实现了变下载边写入操作,所以不用开发人员担心内存问题
3.文件下载后默认保存在tmp文件目录,需要开发人员手动的剪切到合适的沙盒目录

3⃣️NSURLSessionDownloadTask实现大文件离线断点下载(完整)

//1. 创建一个输入流,数据追加到文件的屁股上
//把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建
NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];

//2. 打开流
[stream open];

//3. 写入流数据
[stream write:data.bytes maxLength:data.length];

//4.当不需要的时候应该关闭流
[stream close];

2.关于网络请求请求头的设置(可以设置请求下载文件的某一部分)

//1. 设置请求对象
//1.1 创建请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];

//1.2 创建可变请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//1.3 拿到当前文件的残留数据大小
self.currentContentLength = [self FileSize];

//1.4 告诉服务器从哪个地方开始下载文件数据
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];
NSLog(@"%@",range);

//1.5 设置请求
[request setValue:range forHTTPHeaderField:@"Range"];

3.NSURLSession对象的释放

-(void)dealloc
{
//在最后的时候应该把session释放,以免造成内存泄露
// NSURLSession设置过代理后,需要在最后(比如控制器销毁的时候)调用session的invalidateAndCancel或者resetWithCompletionHandler,才不会有内存泄露
// [self.session invalidateAndCancel];
[self.session resetWithCompletionHandler:^{

    NSLog(@"释放---");
}];

}

4⃣️NSURLSession实现文件上传

}

/*
调用该方法上传文件数据
如果文件数据很大,那么该方法会被调用多次
参数说明:
totalBytesSent:已经上传的文件数据的大小
totalBytesExpectedToSend:文件的总大小
*/

关于NSURLSessionConfiguration相关

01 作用:可以统一配置NSURLSession,如请求超时等
02 创建的方式和使用

//创建配置的三种方式

//统一配置NSURLSession
-(NSURLSession *)session
{
if (_session == nil) {

    //创建NSURLSessionConfiguration
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

    //设置请求超时为10秒钟
    config.timeoutIntervalForRequest = 10;

    //在蜂窝网络情况下是否继续请求(上传或下载)
    config.allowsCellularAccess = NO;

    _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;

}

四.使用AFNetworking来实现NSURLSession网络连接

//
// AFNViewController.m
// FHYNetworkHandle
//
// Created by 付寒宇 on 15/11/7.
// Copyright © 2015年 付寒宇. All rights reserved.
//

import "AFNViewController.h"

import "FHYNetWork.h"

@interface AFNViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@property (strong, nonatomic) IBOutlet UIProgressView *progressView;
@property (nonatomic, strong) AFURLSessionManager *manager;
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSData *partialData;
@end

@implementation AFNViewController

}

五.封装NSURLSession网络连接

ps:参考连接以及推荐阅读

原文:From NSURLConnection to NSURLSession https://www.objc.io/issues/5-ios7/from-nsurlconnection-to-nsurlsession/
译文:从 NSURLConnection 到 NSURLSession http://objccn.io/issue-5-4/

原文:AFNetworking 3.0 Migration Guide https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-3.0-Migration-Guide
译文:AFNetworking 3.0迁移指南 http://www.jianshu.com/p/047463a7ce9b

end

上一篇下一篇

猜你喜欢

热点阅读