博客> NSURLSession之我见
NSURLSession之我见
2017-08-14 18:21 评论:1 阅读:1357 tianya2416
NSURLSession 网络请求 断点续传 上传

前言

iOS7的时候苹果推出了NSURLSession,NSURLSession可以看做是NSURLConnection的进化版,大有取代NSURLConnection的意思

NSURLSession优点:

1、后台上传和下载:只需在创建NSURLSession的时候配置一个选项,就能得到后台网络的所有好处。这样可以延长电池寿命,并且还支持UIKit的多task,在进程间使用相同的委托模型。

2、能够暂停和恢复网络操作:使用NSURLSession API能够暂停,停止,恢复所有的网络任务,再也完全不需要子类化NSOperation.

3、可配置的容器:对于NSURLSession里面的requests来说,每个NSURLSession都是可配置的容器。举个例来说,假如你需要设置HTTP header选项,你只用做一次,session里面的每个request就会有同样的配置。

4、提高认证处理:认证是在一个指定的连接基础上完成的。在使用NSURLConnection时,如果发出一个访问,会返回一个任意的request。此时,你就不能确切的知道哪个request收到了访问。而在NSURLSession中,就能用代理处理认证。

5、丰富的代理模式:在处理认证的时候,NSURLConnection有一些基于异步的block方法,但是它的代理方法就不能处理认证,不管请求是成功或是失败。在NSURLSession中,可以混合使用代理和block方法处理认证。

6、上传和下载通过文件系统:它鼓励将数据(文件内容)从元数据(URL和settings)中分离出来。

7、苹果不在更新和维护NSURLConnection

NSURLSession缺点:

不支持iOS7以下系统NSURLConnection

NSURLSession使用流程:

1、创建一个NSURLSessionConfiguration,设置工作模式和网络设置:

工作模式分为: 

一般模式(default):工作模式类似于原来的NSURLConnection,可以使用缓存的Cache,Cookie,鉴权。 
及时模式(ephemeral):不使用缓存的Cache,Cookie,鉴权。 
后台模式(background):在后台完成上传下载。 

网络设置: 

比如超时设置,缓存,是否允许使用蜂窝网络等
@property NSTimeInterval timeoutIntervalForRequest;
@property NSURLRequestCachePolicy requestCachePolicy;
@property BOOL allowsCellularAccess;
@property  BOOL discretionary ;  

allowsCellularAccess 属性指定是否允许使用蜂窝连接;
discretionary属性为YES时表示当程序在后台运作时由系统自己选择最佳的网络连接配置,该属性可以节省通过蜂窝连接的带宽。在使用后台传输 数据的时候,建议使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内。 

补充:这个标志允许系统为分配任务进行性能优化。这意味着只有当设备有足够电量时,设备才通过Wifi进行数据传输。如果电量低,或者只仅有一个蜂窝连接,传输任务是不会运行的。后台传输总是在discretionary模式下运行。

2、根据第一步创建的NSURLSessionConfiguration创建一个NSURLSession,系统提供了三种创建方法:

//配置 Session 
+ (NSURLSession *)sharedSession;全局单例

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; 

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;

sessionWithConfiguration:根据给定的NSURLSessionConfiguration创建一个Session,系统默认创建一个新的串行OperationQueue处理Session的消息。 

sessionWithConfiguration:delegate:delegateQueue:,可以设定回调的delegate(注意这个回调delegate会被强引用),并且可以设定delegate在哪个 OperationQueue回调,如果将其设置为[NSOperationQueue mainQueue]就能在主线程进行回调。 

3、通过NSURL或者NSURLRequest创建一个NSURLSessionTask,调用resume开始工作。可以用taskwithurl或者taskwithrequest创建。每个task支持cancel,suspend,resume

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;

- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;

- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;

NSURLSessionTask有三个子类: 

NSURLSessionDataTask:可以上传内容,上传完成后再进行下载。返回的数据存放在内存中。发送接收数据都用NSData表示。 
NSURLSessionUploadTask:上传用的Task,传完以后不会再下载返回结果;上传数据为文件 
NSURLSessionDownloadTask:下载用的Task。下载数据先写入到一个临时文件里,支持后台下载(在后台模式下,app在后台或者不运行,downloadtask都可以运行)

4、设置delegate,completionhandler

在上一步请求中的completionHandler  block实现结果解析(nsdata需要根据接口具体情况解析成可以理解的数据,如json/xml/plist等);也可以不在block中进行相关操作,而是实现相关的代理方法(需要创建session的时候先设置session的delegate),对相关的结果和进度等进行处理。

@protocol NSURLSessionDelegate <NSObject>  // session的代理,相当于所有协议的父类  

@protocol NSURLSessionTaskDelegate <NSURLSessionDelegate>  // task的代理,其父协议是NSURLSessionDelegate
@protocol NSURLSessionDataDelegate <NSURLSessionTaskDelegate> // datatask的代理,其父协议是NSURLSessionTaskDelegate
@protocol NSURLSessionDownloadDelegate <NSURLSessionTaskDelegate>  // downloadtask的代理,其父协议是NSURLSessionDataDelegate

1、网络请求

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];
 NSURLSession *session = [NSURLSession sharedSession];

 NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

     }];
 [task resume];

 2、数据上传 

 NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];
 NSData *data = ...;
 NSURLSession *session = [NSURLSession sharedSession];

 NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {

}];

 [uploadTask resume];

3 数据下载

 NSURL *URL = [NSURL URLWithString:@"http://example.com/file.zip"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];
 NSURLSession *session = [NSURLSession sharedSession];

 NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler: ^(NSURL *location, NSURLResponse *response, NSError *error) {
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
        [documentsDirectoryURL URLByAppendingPathComponent:[[response URL] lastPathComponent]];
    }];
 [downloadTask resume];

暂停继续下载/断点下载

NSData *resumeData;
resumeData 为暂停时已经下载的数据
NSURLSessionDownloadTask * task  = [session downloadTaskWithResumeData:resumeData];

4、使用delegate完成数据下载

    NSString *imageUrl = @"http://www.raywenderlich.com/images/store/ iOS7_PDFonly_280@2x_authorTBA.png";
    NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session =[NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

    NSURLSessionDownloadTask * getImageTask = [session downloadTaskWithURL:[NSURL URLWithString:imageUrl]  completionHandler:^(NSURL *location,                     NSURLResponse *response,NSError *error) {

        UIImage * downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"刷新UI");
        });
    }];  
    [getImageTask resume];

记住实现delegate方法

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{

}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{

}

未完待续

收藏
7
sina weixin mail 回到顶部