NSURLSessionDownloadTask在NSURLSession后台会话中提供错误

时间:2016-11-07 06:44:34

标签: ios objective-c nsurlsession

我正在学习NSURLSession来制作一个自定义的网络课程,偶然发现了一个非常不寻常的错误。

我的目标很简单,我想在完成后写一个文件中URL的响应。所以我创建了一个下载任务并将其分配给 defaultSessionConfiguration 。在将委托分配给配置而不将委托分配给配置(在这种情况下,完成处理程序工作)的两种情况都有效。

现在我转移到 backgroundSessionConfigurationWithIdentifier 。后台会话不支持块,因此委托调用是强制性的。

每次都以错误结束。 错误在下面给出

Printing description of error:
Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo={NSErrorFailingURLKey=http://__________________, NSErrorFailingURLStringKey=http://__________________, NSLocalizedDescription=unknown error}

我认为我必须编写背景配置错误,所以我通过创建演示下载任务来测试它,以下载图像并将此任务添加到此后台会话。 这次工作

有效的代码如下:

+ (CustomNetwork *)sharedNetworkObject
{
     if(!netWorkObj)
     {
          netWorkObj = [[CustomNetwork alloc] init];

          //[netWorkObj prepareDataSession];

          //[netWorkObj prepareBackgroundSession];
     }
     return netWorkObj;
}
//
+ (NSOperationQueue *)responseQueue
{
     if(!queue)
     {
          queue = [[NSOperationQueue alloc] init];
     }
     return queue;
}

- (void)prepareDataSession
{
     if(!dataSession)
     {
          NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
          configuration.HTTPMaximumConnectionsPerHost = 5; // This means 1 session can hold to 5 connections
          configuration.timeoutIntervalForRequest = CONNECTION_TIME_OUT;
          configuration.timeoutIntervalForResource = CONNECTION_TIME_OUT;
          dataSession = [NSURLSession sessionWithConfiguration:configuration
                                                      delegate:nil //[CustomNetwork sharedNetworkObject]
                                                 delegateQueue:nil];
     }
}

- (void)prepareBackgroundSession
{
     if(!backgroundSession)
     {
          NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"backgroundSession"];
          configuration.HTTPMaximumConnectionsPerHost = 5; // This means 1 session can hold to 5 connections
          configuration.timeoutIntervalForRequest = CONNECTION_TIME_OUT;
          configuration.timeoutIntervalForResource = CONNECTION_TIME_OUT;
          configuration.discretionary = NO;// For optimizing
          backgroundSession = [NSURLSession sessionWithConfiguration:configuration
                                                      delegate:[CustomNetwork sharedNetworkObject]
                                                 delegateQueue:nil];
     }
}

+ (void)demoBackGroundSessionWorks
{
     NSURL * url = [NSURL URLWithString:@"https://www.wallpapereast.com/static/images/wallpaper-photos-42.jpg"];//@"http://www.hdwallpapersinn.com/wp-content/uploads/2012/09/HD-Wallpaper-1920x1080.jpg"];
     //NSURLSessionConfiguration * backgroundConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:@"backgroundtask1"];

     [[CustomNetwork sharedNetworkObject] prepareBackgroundSession];

     NSURLSessionDownloadTask * downloadTask =[backgroundSession downloadTaskWithURL:url];
     [downloadTask resume];

}

失败的代码是:

    +(void)createDownloadConnectionWithUrl:(NSString *)aUrl
                                                    operationKey:(NSString *)operationKey
                                                       jsonParam:(NSString *)jsonString
                                                      HTTPMethod:(NSString *)method
                                                  startImmediate:(BOOL)startImmediate
                                                    downloadPath:(NSString *)downloadPath

    {
         if([[aUrl trimmedString] length] && [self isValidMethod:method] && [[downloadPath trimmedString] length])
         {
              CustomURLRequest *dataRequest = [CustomNetwork requestURLWithString:aUrl];
              dataRequest.downloadDestinationPath = downloadPath;

              [self prepareTheDataRequest:&dataRequest
                           WithParameters:&jsonString
                                ForMethod:&method
                          andOpertaionKey:operationKey];


              // Remove any file if present in the path
              if([[NSFileManager defaultManager] fileExistsAtPath:downloadPath])
              {
                   [[NSFileManager defaultManager] removeItemAtPath:downloadPath error:nil];
              }

              // PS : if you are using BackGroundSession, completion block wont work and will give to a NSGenericException. Reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'

              [[CustomNetwork sharedNetworkObject] prepareBackgroundSession];
              NSURLSessionDownloadTask *downloadTask =  [backgroundSession downloadTaskWithRequest:dataRequest];

if(startImmediate)
          {
               [downloadTask resume];
          }
}

prepare方法为请求添加标题。

如果我使用 dataSession 而不是 backgroundSession

,那么失败的代码将会有效

问:同样的请求在defaultConfiguration中有效但在backgroundSession中失败。我是否遗漏了某些内容或与#34; 仅支持上传和下载任务(无数据任务)" Apple Docs的学说。

1 个答案:

答案 0 :(得分:0)

后台会话不关心他们正在下载什么(文件或任意数据或其他)。您只需使用下载任务或上载任务,而不是数据任务。但是你这样做了。

我的猜测是,CustomURLRequestNSURLRequest的子类,而没有看到其余的代码。不幸的是,NSURLRequest的子类支持NSURLSession - 特别是实际直接添加属性的子类。在各种版本的iOS和OS X中,您遇到的错误范围从严重到完全破坏。我甚至看到过一种情况,你从一个请求中获取自定义属性值以及来自完全不同的请求的URL和头文件。

您应该在NSURLRequest上创建自定义类别,而不是子类。在该类别中,创建getter和setter方法。

  • [NSURLProtocol propertyForKey:inRequest:]用于吸气剂。
  • 使用[NSURLProtocol setProperty:forKey:inRequest:]作为您的安装人员。

重要事项:使用这些方法存储在NSURLRequest内的所有对象必须属性列表序列化。如果您需要将自定义类的实例与NSURLRequest相关联,则应将它们存储在单独的NSDictionary中,并使用任意字典键(例如调用[[NSUUID UUID] UUIDString]的结果),您可以安全地存储在NSURLRequest对象中,然后用于从外部字典中获取自定义类。