Objective c NSURLSessionDownloadTask在使用后台配置时不断重试

Objective c NSURLSessionDownloadTask在使用后台配置时不断重试,objective-c,background,timeout,nsurlsession,nsurlsessionconfiguration,Objective C,Background,Timeout,Nsurlsession,Nsurlsessionconfiguration,我有一个问题,当谈到一个缓慢的后端和下载数据与后台配置 NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; _backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

我有一个问题,当谈到一个缓慢的后端和下载数据与后台配置

NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithURL:URL];
[downloadTask resume];
如果连接已断开,但需要60秒以上才能发回数据,则会发生超时。那很好。然而,我所经历的行为是,我没有犯错误。会话只是发送一个新请求。“再给我一次数据”。我不知道这发生在哪里。我的代码中没有,而且我知道没有调用委托方法。我只能访问服务器日志。服务器发回数据大约需要68秒,但应用程序只是忽略了数据,因为它正在等待新的请求

一种解决方案是增加超时值。但我不喜欢它,它只适用于iOS 7。不是iOS 8

sessionConfig.timeoutIntervalForRequest = 10 * 60.0;
有人对此有什么见解吗?
我在stackoverflow上找到了这个。它已经10个月了,但没有解决方案,只有人们同意。

我设法解决了它。我不是说我的解决方案是解决方案,而是解决方案

我所经历的行为是,iOS 7和iOS 8对属性的优先级不同。我有两个地方可以设置这些超时属性,NSURLSessionConfigurationNSMutableURLRequest中。iOS 7不关心requests属性,iOS 8不关心configurations属性。现在,我的解决方案如下所示:

NSURLSessionConfiguration *sessionConfig;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
}
else {
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
}
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
    sessionConfig.timeoutIntervalForRequest = 5 * 60.0;
}
_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
    request.timeoutInterval = 5 * 60.0;
}
NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithRequest:request];
我不是说应该改变。这是我们为特定环境设置所做的决定。

更新

我们将TimeOutiterValforResource更改回默认值7天。例如,我们在中国有客户,其中一些客户的联系非常差。10分钟的总时限太傻了


确保检查出更好的代码质量。然而,我的代码片段分布在不同的类中,所以我不能100%地重用这种方法。

我无法阻止自己,下面是你的答案,有点重构:)


自iOS8以来,如果服务器没有响应,则后台模式下的NSUrlSession不会调用此委托方法<代码>-(void)URLSession:(NSURLSession*)会话任务:(NSURLSessionTask*)任务未完成错误:(NSError*)错误 下载/上传无限期保持空闲状态。当服务器没有响应时,在iOS7上调用此委托时出错

通常,如果线路出现问题,NSURLSession后台会话不会使任务失败。相反,它会继续寻找运行请求的好时机,并在此时重试。这将一直持续到资源超时过期(即,用于创建会话的NSURLSessionConfiguration对象中的TimeOutiterValforResource属性的值)。该值的当前默认值为一周!换句话说,iOS7中超时失败的行为是不正确的。在后台会话的上下文中,更有趣的是不要因为网络问题而立即失败。因此,自iOS8以来,即使遇到超时和网络丢失,NSURLSession任务仍将继续。但是,它将继续,直到达到TimeOutiterValforResource

所以基本上,TimeOutiterValforRequest在后台会话中不起作用,但TimeOutiterValforResource会起作用


来源:

另一个与服务器对后台上传任务的响应时间过长时发生的重试循环有关的Apple讨论:


非常漂亮,易于阅读,谢谢!虽然我的代码片段实际上分布在两个不同的类中,但我将尽我所能应用它:)问题:为什么要区分iOS 8和iOS 7?您不能同时设置TimeOutiterValforRequest和TimeOutiterVal吗?
sessionConfig.timeoutIntervalForResource = 10 * 60;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
NSURLSessionConfiguration *sessionConfig;
float timeout = 5 * 60.0f;

BOOL iOS8OrNewer = [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0;
if (iOS8OrNewer) {
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
    request.timeoutInterval = timeout;
}
else {
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
    sessionConfig.timeoutIntervalForRequest = timeout;
}

_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithRequest:request];