NSURLSession:如何增加URL请求的超时时间?

90

我正在使用iOS 7的新NSURLSessionDataTask来检索数据,方法如下:

NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:
request completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
//
}];

如何增加超时时间以避免错误"The request timed out" (在 NSURLErrorDomain Code=-1001 中)?

我已经查阅了NSURLSessionConfiguration的文档,但未找到设置超时值的方法。

感谢您的帮助!


1
你是否正在进行许多请求?如果是这样,仅仅增加超时时间可能不是正确的方法,而是你想要限制尝试的并发请求数量(例如使用NSOperationQueuemaxConcurrentOperationCount)。如果你正在使用非委托基础版本的NSURLSession并且正在使用完成块版本,则这并不太复杂。由于NSURLSession架构存在重大问题,如果使用基于委托的方法,正确地执行此操作可能会有些麻烦。 - Rob
2
我的主要问题是HTTP服务器(我无法控制)有时负载很重,响应非常缓慢。您是否知道sharedSession超时的默认值? - AlexR
不是的,但正如其他人所说,您应该创建自己的defaultSessionConfiguration并设置适合您的服务器的timeOutIntervalForRequest。问题在于,由于发出了超过四到五个并发请求而导致的超时问题是完全不同的问题,并且需要不同的解决方案。但是,如果您只发出一到两个请求并且它们仍然超时,则设置timeoutInterval属性是正确的方法。 - Rob
7个回答

156

ObjC

NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;

Swift

let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30.0
sessionConfig.timeoutIntervalForResource = 60.0
let session = URLSession(configuration: sessionConfig)

文档说明

timeoutIntervalForRequesttimeoutIntervalForResource分别指定请求和资源的超时时间间隔。

timeoutIntervalForRequest - 在等待额外数据时使用的超时时间间隔。每当接收到新数据时,与此值关联的计时器都会被重置。当请求计时器达到指定的时间间隔且没有接收到任何新数据时,它会触发超时。

timeoutIntervalForResource - 允许资源请求消耗的最长时间。该值控制在放弃之前要等待整个资源传输的时间。当请求启动时,资源计时器开始计数,直到请求完成或达到此超时间隔为止,以先到者为准。

参考自NSURLSessionConfiguration 类参考


7
您好,Reecon。我希望我的Web服务的超时时间为180秒(3分钟)。因为我了解到NSURLSESSION及其timeoutIntervalForRequest和timeoutIntervalForResource方法,我尝试使用这些方法,但设置超时时间为180秒(sessionConfig.timeoutIntervalForRequest = 180.0; sessionConfig.timeoutIntervalForResource = 180.0;),但是我仍然在75秒或一些随机时间间隔内收到失败回调,显示“请求已超时”。您有任何想法吗? - XiOS
我认为通过苹果的文档得知,对[NSURLSessionConfiguration defaultSessionConfiguration]的更改不会影响[NSURLSession sharedSession] - xi.lin
9
请注意,timeoutIntervalForRequest 的默认超时时间为60秒,timeoutIntervalForResource 的默认超时时间为7天。 - Adam Johns
6
当timeoutIntervalForRequest的值设置为低于60时,它会起作用,但当我将其设置为更高的值时,超时会在60秒后发生... - Diogo Souza
@DiogoSouza 我也遇到了类似的问题,如果超时时间小于60,它可以工作,否则就不行了,你找到任何解决方案了吗? - Saif
显示剩余4条评论

19

如果有Swift开发人员来到这里

要实现这一点,你需要使用

    let urlconfig = NSURLSessionConfiguration.defaultSessionConfiguration()
    urlconfig.timeoutIntervalForRequest = 12
    urlconfig.timeoutIntervalForResource = 12
    self.session = NSURLSession(configuration: urlconfig, delegate: self.delegates, delegateQueue: nil)

我在timeoutIntervalForRequest上收到了一个未识别的选择器发送给实例错误。 - Marcus
我已经更新到Swift 3,但是我收到了“Class has no member delegates”错误。 - adamprocter
@sruit-a-suk "let" 不是不可变的,而 "var" 是可变的。所以超时请求和资源永远不会被设置吗? - Matthew Ferguson

11

在Swift 3中,超时时间为15秒。

    let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = TimeInterval(15)
    configuration.timeoutIntervalForResource = TimeInterval(15)
    let session = URLSession(configuration: configuration)

1
这并没有解释timeoutIntervalForRequesttimeoutIntervalForResource之间的区别。 - Martin

11

我的情况是我增加了错误类的超时时间。通过增加 URLRequest 而不是 URLSession 的超时时间,我的超时错误问题得以解决。

var request = URLRequest(url: url)
request.timeoutInterval = 30

2
这就是解决超时问题的方法。我预计这需要与上述设置一起使用。 - arcady bob

4

NSURLSessionConfiguration 包含 timeoutIntervalForRequest 属性:

@property NSTimeInterval timeoutIntervalForRequest

控制超时时间。还有timeoutIntervalForResource用于请求发起后的超时时间。


3

针对Swift 4:

let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = TimeInterval(15)
config.timeoutIntervalForResource = TimeInterval(15)
let urlSession = URLSession(configuration: config)

timeoutIntervalForRequest属性用于基于此配置的会话中的所有任务。 timeoutIntervalForResource属性用于基于此配置的会话中的所有任务。


3

在 SWIFT 3.0 中,您需要使用

 if let cleanURLString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
    let theURL: Foundation.URL = Foundation.URL(string: cleanURLString) {

    var task:URLSessionDataTask?
    let urlconfig = URLSessionConfiguration.default
    urlconfig.timeoutIntervalForRequest = 20
    urlconfig.timeoutIntervalForResource = 60
    let session = Foundation.URLSession(configuration: urlconfig, delegate: self, delegateQueue: OperationQueue.main)

    let request = URLRequest(url: theURL)
    request.httpMethod = "POST"
    request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
    let paramString = YourParameterString
    request.httpBody = paramString.data(using: String.Encoding.utf8)

    task = session.dataTask(with: request) {
        (data, response, error) in
        // Do here
    })
    dataTask.resume()
}

请注意,即使在会话已经创建后,也可以更改超时时间:let session = Foundation.URLSession(configuration: ... ); session.configuration.timeoutIntervalForRequest = 20。然而,对于 .background 会话,这种方式似乎不起作用。 - Vitalii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接