使用后台配置时,NSURLSessionTask永远不会在超时后回叫 [英] NSURLSessionTask never calls back after timeout when using background configuration

查看:323
本文介绍了使用后台配置时,NSURLSessionTask永远不会在超时后回叫的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在后台会话中使用NSURLSessionDownloadTask来实现我的所有REST请求.这样,我可以使用相同的代码,而不必考虑我的应用程序是在后台还是在前台.

I am using NSURLSessionDownloadTask with background sessions to achieve all my REST requests. This way I can use the same code without have to think about my application being in background or in foreground.

我的后端已经死了一段时间了,我借此机会测试了NSURLSession在超时情况下的表现.

My back-end has been dead for a while, and I have taken that opportunity to test how does NSURLSession behave with timeouts.

令我惊讶的是,我的NSURLSessionTaskDelegate回调都没有被调用过.无论我在NSURLRequestNSURLSessionConfiguration上设置了什么超时,我都不会从iOS收到任何回调,告诉我请求确实以超时完成.

To my utter surprise, none of my NSURLSessionTaskDelegate callbacks ever gets called. Whatever timeout I set on the NSURLRequest or on the NSURLSessionConfiguration, I never get any callback from iOS telling me that the request did finish with timeout.

也就是说,当我在后台会话中启动NSURLSessionDownloadTask时.应用程序在后台或前台也会发生相同的行为.

That is, when I start a NSURLSessionDownloadTask on a background session. Same behavior happens the application is in background or foreground.

示例代码:

- (void)launchDownloadTaskOnBackgroundSession {
    NSString *sessionIdentifier = @"com.mydomain.myapp.mySessionIdentifier";
    NSURLSessionConfiguration *backgroundSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:sessionIdentifier];
    backgroundSessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    backgroundSessionConfiguration.timeoutIntervalForRequest = 40;
    backgroundSessionConfiguration.timeoutIntervalForResource = 65;
    NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundSessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.timeout.com/"]];
    request.timeoutInterval = 30;
    NSURLSessionDownloadTask *task = [backgroundSession downloadTaskWithRequest:request];
    [task resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"URLSession:task:didCompleteWithError: id=%d, error=%@", task.taskIdentifier, error);
}

但是,当我使用默认会话时,则在30秒(我在请求级别设置的超时)后收到错误回调.

However, when I use the default session, then I do get an error callback after 30seconds (the timeout that I set at request level).

示例代码:

- (void)launchDownloadTaskOnDefaultSession {
    NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    defaultSessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
    defaultSessionConfiguration.timeoutIntervalForRequest = 40;
    defaultSessionConfiguration.timeoutIntervalForResource = 65;
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.timeout.com/"]];
    request.timeoutInterval = 30;
    NSURLSessionDownloadTask *task = [defaultSession downloadTaskWithRequest:request];
    [task resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    NSLog(@"URLSession:task:didCompleteWithError: id=%d, error=%@", task.taskIdentifier, error);
}

我似乎无法在文档中找到任何暗示使用后台会话时超时行为有所不同的内容.

I cannot seem to find in the documentation anything that suggests that the timeout should behave differently when using background sessions.

有人也遇到过这个问题吗? 那是错误还是功能?

Has anyone bumped into that issue as well? Is that a bug or a feature?

我正在考虑创建一个错误报告,但是与SO(六个月)相比,我通常在SO(几分钟)上得到的反馈要快得多.

I am considering creating a bug report, but I usually get feedback much faster on SO (a few minutes) than on the bug reporter (six months).

此致

推荐答案

自iOS8起,如果服务器不响应,则后台模式下的NSUrlSession不会调用此委托方法. -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
下载/上传无限期保持空闲状态. 服务器未响应时,在iOS7上调用此委托时发生错误.

Since iOS8, the NSUrlSession in background mode does not call this delegate method if the server does not respond. -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
The download/upload remains idle indefinitely. This delegate is called on iOS7 with an error when the server does not respond.

通常,如果出现以下情况,NSURLSession后台会话不会使任务失败 电线上出了点问题.而是继续寻找 是时候运行请求并在那时重试.这继续 直到资源超时到期(即 NSURLSessionConfiguration中的timeoutIntervalForResource属性 用于创建会话的对象).当前的默认值 价值是一个星期!

In general, an NSURLSession background session does not fail a task if something goes wrong on the wire. Rather, it continues looking for a good time to run the request and retries at that time. This continues until the resource timeout expires (that is, the value of the timeoutIntervalForResource property in the NSURLSessionConfiguration object you use to create the session). The current default for that value is one week!

从此源获取的引用信息

换句话说,iOS7中超时失败的行为是不正确的.在后台会话的上下文中,更有趣的是不会由于网络问题而立即失败.因此,自iOS8起,即使遇到超时和网络丢失,NSURLSession任务也会继续.但是,它一直持续到达到timeoutIntervalForResource.

In other words, the behaviour of failing for a timeout in iOS7 was incorrect. In the context of a background session, it is more interesting to not fail immediately because of network problems. So since iOS8, NSURLSession task continues even if it encounters timeouts and network loss. It continues however until timeoutIntervalForResource is reached.

因此,基本上timeoutIntervalForRequest在后台会话中不起作用,但timeoutIntervalForResource将起作用.

So basically timeoutIntervalForRequest won't work in Background session but timeoutIntervalForResource will.

这篇关于使用后台配置时,NSURLSessionTask永远不会在超时后回叫的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆