我正在学习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的学说。
答案 0 :(得分:0)
后台会话不关心他们正在下载什么(文件或任意数据或其他)。您只需使用下载任务或上载任务,而不是数据任务。但是你这样做了。
我的猜测是,CustomURLRequest
是NSURLRequest
的子类,而没有看到其余的代码。不幸的是,NSURLRequest
的子类不支持NSURLSession
- 特别是实际直接添加属性的子类。在各种版本的iOS和OS X中,您遇到的错误范围从严重到完全破坏。我甚至看到过一种情况,你从一个请求中获取自定义属性值以及来自完全不同的请求的URL和头文件。
您应该在NSURLRequest
上创建自定义类别,而不是子类。在该类别中,创建getter和setter方法。
[NSURLProtocol propertyForKey:inRequest:]
用于吸气剂。[NSURLProtocol setProperty:forKey:inRequest:]
作为您的安装人员。 重要事项:使用这些方法存储在NSURLRequest
内的所有对象必须属性列表序列化。如果您需要将自定义类的实例与NSURLRequest
相关联,则应将它们存储在单独的NSDictionary
中,并使用任意字典键(例如调用[[NSUUID UUID] UUIDString]
的结果),您可以安全地存储在NSURLRequest
对象中,然后用于从外部字典中获取自定义类。