美文网首页
NSURLSession

NSURLSession

作者: linatan | 来源:发表于2016-07-25 21:11 被阅读136次

    Using NSURLSession
    NSURLSession API

    会话类型

    1. default session:与其他下载URL的Foundation方法类似,使用基于磁盘的缓存策略,并在用户的keychain中存储证书
    2. Ephemeral session:不存储任何数据到磁盘中,所有缓存、证书存储都保存在RAM中并与会话绑定,应用结束会话时,这些都会被释放
    3. background session:类似于default session,除了有一个独立的进程进行来处理所有的数据传输。
    4. 还有个单例 shared session,没有configuration。

    任务类型

    1. data tasks:使用NSData对象来发送和接收数据。数据任务可以分片返回数据,也可以通过完成处理器一次性返回数据。由于数据任务不存储数据到文件,所以不支持background session
    2. download tasks:以文件的形式接收数据,当程序不运行时支持后台下载
    3. upload tasks:通常以文件的形式发送数据,支持background session

    后台传输

    NSURLSession支持在应用挂起时在后台传输数据,后台传输只由使用background session配置的对象创建的会话进行调用,backgroundSessionConfigurationWithIdentifier:
    使用后台会话时,由于其是在一个独立的进程中传输,且重启应用进程相当损耗资源,只有少量特性可以使用,所以有以下限制:

    1. 会话必须提供事件分发(event delivery)代理
    2. 只支持http和https协议
    3. 总是伴随重定向
    4. 只有从文件中upload tasks才可以,从data objects或者stream将会失败
    5. 如果当应用在后台时初始化的后台传输,则配置对象的discretionary属性为true

    在iOS中,当我们的应用不再运行时,如果后台下载任务完成或者需要证书,则系统会在后台自动重启我们的应用,同时调用UIApplicationDelegate对象的application:handlerEventsForBackgroundURLSession:completionHandler:方法。这个调用会提供启动的应用的session的标识。我们的应用应当存储completion handler,使用相同的标识来创建后台配置对象,然后使用配置对象来创建会话。新的会话会与运行的后台activity关联。当会话完成后台下载任务时,会给会话代理发送一个URLSessioinDidFinishEventsForBackgroundURLSession:消息。代理对象然后在main thread调用存储的completion handler,这样操作系统才知道再次暂停你的应用是安全的。
    如果在程序挂起时有任何任务完成,则会调用URLSession:downloadTask:didFinishDownloadingToURL:方法。
    同样的,如果任务需要证书,则NSURLSession对象会在适当的时候调用URLSession:task:didReceiveChallenge:completionHandler: 和URLSession:didReceiveChallenge:completionHandler:方法。

    会话和任务对象实现了NSCopying协议:

    1. 当应用拷贝一个会话或任务对象时,会获取相同对象的指针(未创建新对象)
    2. 当应用拷贝一个配置对象时,会获取一个可单独修改的新的对象(创建新对象)

    NSURLSession的生命周期

    Life Cycle of a URL Session
    中文翻译

    创建和配置NSURLSession

    配置选项

    1. 支持对缓存、cookies、证书的私有存储 ,以及对单例会话特定的protocol
    2. 关联到一个特定请求(任务),或者一组请求(会话)的认证
    3. 可以通过url上传或者下载文件
    4. 配置主机的最大连接数
    5. 当资源无法在一个确定时间内下载时,配置一个超时时间
    6. 支持安全传输协议TLS的版本区间
    7. 自定义代理字典
    8. cookie的控制策略
    9. HTTP的传输控制

    因为大部分的配置都在一个configuration对象中设置,可以重用一些基本设置;你可以在任何时间安全的修改一个configuration对象。因为当创建一个会话时,configuration对象的传递是由深拷贝实现的,所以修改只会影响之后新创建的会话,不会对已存在的会话造成影响。初始化一个会话对象(session object)可以进行如下操作:

    1. 一个configuration对象用来管理会话或任务的行为
    2. optional:一个代理对象用来表示接收数据的进度,会话任务或会话其他事件的进度,比如服务器认证,决定一个加载请求是否可转换为下载请求等等
    3. 如果没有指定一个代理,NSURLSession对象将使用系统默认提供的代理。在这种方式中,你可以轻松的使用NSURLSession方法替代已存在的sendAsynchronousRequest:queue:completionHandler:方法

    app在后台传输数据,必须自定义代理

    Demo——利用配置项创建NSURLSession

    - (void)setUpSession
    {
        NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSessionConfiguration *ephemeralConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
        NSURLSessionConfiguration *backgroundConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"backgroundConfiguration"];
        
        //针对defaultConfiguration配置cache
        NSString *cacheDirectory =  NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
        NSString *cachePath = [cacheDirectory stringByAppendingString:@"myCache"];
        
        NSURLCache *cacheUrl = [[NSURLCache alloc]initWithMemoryCapacity:16384 diskCapacity:268435456 diskPath:cachePath];
        defaultConfiguration.URLCache = cacheUrl;
        defaultConfiguration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
        
        NSOperationQueue *operationQueue = [NSOperationQueue mainQueue];
        //创建session
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfiguration delegate:self delegateQueue:operationQueue];
        //...
    }
    

    使用系统提供的代理获取资源

    - (void)getDataWithSystemDefaultDelegate
    {
        NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        NSURLSession *sessionWithoutADelegate = [NSURLSession sessionWithConfiguration:defaultConfiguration];
        NSURL *url = [NSURL URLWithString:@"https://www.example.com/"];
        
        [[sessionWithoutADelegate dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"Got response %@ with error %@.\n", response, error);
            NSLog(@"DATA:\n%@\nEND DATA\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
                  }] resume];
    }
    

    使用自定义的代理获取资源

    需要实现如下2个方法:
    URLSession:dataTask:didReceiveData:
    URLSession:task:didCompleteWithError:

    下载文件

    app需要实现以下的代理方法

    1. URLSession:downloadTask:didFinishDownloadingToURL:提供下载内容临时存储的目录地址。注意:在这个方法返回之前,必须打开文件来进行读取或者将下载内容移动到一个永久目录;当方法返回后,临时文件将会被删除。
    2. URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:提供下载的进度信息
    3. URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:告诉app尝试恢复之前失败的下载
    4. URLSession:task:didCompleteWithError:告诉app下载失败
    1. 当下载任务安排在background session中时,当app停止运行时下载继续;
    2. 如果是安排在default/ephemeral session中时,当重新开启app时,下载会重新开始。
    3. 与服务器传输数据期间,如果用户进行了暂停操作,app可以调用cancelByProducingResumeData:方法取消任务。然后,app可以将已传输的数据作为参数传递给downloadTaskWithResumeData:或者downloadTaskWithResumeData:completionHandler:来创建一个新的下载任务继续下载。
      4)如果传输失败,代理会调用URLSession:task:didCompleteWithError:。如果任务可以再运行,userInfo中包含键NSURLSessionDownloadTaskResumeData,可以将数据作为参数传递给downloadTaskWithResumeData:或者downloadTaskWithResumeData:completionHandler:来创建一个新的下载任务进行重试

    上传数据内容

    app可以对Http post请求提供三种方式的请求体:NSData对象、文件、数据流

    NSData上传

    - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request 
                                             fromData:(NSData *)bodyData;
    
    - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request 
                                             fromData:(NSData *)bodyData 
                                    completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;
    

    file上传

    - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request 
                                             fromFile:(NSURL *)fileURL;
    
    - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request 
                                             fromFile:(NSURL *)fileURL 
                                    completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;
    

    stream上传

    - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
    
    - (void)URLSession:(NSURLSession *)session 
                  task:(NSURLSessionTask *)task 
     needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler;
    

    后台任务

    使用NSURLSession,当下载完成时,app将会自动启动;代理中2个主要方法:

    //负责创建session,存储completionHandler
    - (void)application:(UIApplication *)application 
    handleEventsForBackgroundURLSession:(NSString *)identifier 
      completionHandler:(void (^)(void))completionHandler;
    
    - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session;
    

    相关文章

      网友评论

          本文标题:NSURLSession

          本文链接:https://www.haomeiwen.com/subject/dncgjttx.html