【问题标题】:NSURLSessionConfiguration timeoutIntervalForRequest vs NSURLSession timeoutIntervalNSURLSessionConfiguration timeoutIntervalForRequest vs NSURLSession timeoutInterval
【发布时间】:2013-11-10 09:01:40
【问题描述】:

使用新的 NSURLSession,现在在用于创建会话的 NSURLSessionConfiguration 对象上有一个 timeoutIntervalForRequest。

但是NSURLRequest对象上还有一个timeoutInterval,可以用来在session中创建NSURLSessionTask。

我的问题是,如果配置的 timeoutIntervalForRequest 设置为 30,但用于创建任务的 NSURLRequest 的 timeoutInterval 为 60,那么实际会使用哪个超时间隔?

【问题讨论】:

    标签: ios objective-c timeout nsurlsession


    【解决方案1】:

    NSURLSession 提供两个超时,timeoutIntervalForRequesttimeoutIntervalForResource

    timeoutIntervalForRequest 由每次传输数据时重置的计时器强制执行。因此,如果您将此超时设置为 30 秒,并且每 30 秒至少传输一个字节的数据,则永远不会遇到超时。只有在 30 秒内绝对没有数据传输时才会触发超时。您也可以说这是会话任务的最大空闲时间。默认值为 60 秒。

    timeoutIntervalForResource 由永不重置的计时器强制执行。它在会话任务启动时启动,在会话任务停止或完成时停止。所以这是会话任务可以花费的最大总时间,这是大多数人听到“超时”时的想法。由于会话任务也可能是通过非常慢的 Internet 链接下载 100 GB 的文件,因此这里的默认值为 7 天!

    NSURLRequest(及其可变子类)仅提供一个属性timeoutInterval。这个超时值的行为类似于timeoutIntervalForRequest,正如NSURLRequest 的文档所说:

    如果在连接尝试期间请求保持空闲 超过超时间隔,则认为该请求 已超时。

    来源:timeoutInterval - NSURLRequest | Apple Developer Documentation

    NSURLSession 的文档说:

    注意

    在某些情况下,此配置中定义的策略可能是 被提供的 NSURLRequest 对象指定的策略覆盖 为一个任务。尊重请求对象上指定的任何策略 除非会话的政策更严格。

    来源:NSURLSessionConfiguration - Foundation | Apple Developer Documentation

    因此,NSURLRequesttimeoutInterval 将覆盖 NSURLSessiontimeoutIntervalForRequest,但前提是系统认为它“更具限制性”,否则 NSURLSession 的值将胜出。

    【讨论】:

      【解决方案2】:

      自从 n-miyo 测试后,情况似乎发生了变化。

      apple documentation 声明 NSURLRequest 值将覆盖会话配置。

      在某些情况下,此配置中定义的策略可能会被为任务提供的 NSURLRequest 对象指定的策略覆盖。除非会话的策略更具限制性,否则在请求对象上指定的任何策略都会受到尊重。例如,如果会话配置指定不应允许蜂窝网络,则 NSURLRequest 对象无法请求蜂窝网络。

      【讨论】:

        【解决方案3】:

        从 iOS8 开始,后台模式下的 NSUrlSession 如果服务端没有响应就不会调用这个委托方法。 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 下载/上传无限期地保持空闲。当服务器没有响应时,在 iOS7 上调用此委托时出现错误。

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

        所以基本上 timeoutIntervalForRequest 不会在后台会话中工作,但 timeoutIntervalForResource 会。

        我从developer forum 的一位 Apple 员工那里得到了这个答案。另外,我已经通过实施验证了这一点。

        【讨论】:

        • 我正在使用 NSURLSession 检查给定的 url 是否仍然处于活动状态或已损坏,关于我应该将timeoutIntervalForResource 设置为什么时间的任何建议?我的目标是设置它,以便确定 url 是否处于活动状态所需的绝对最短时间?
        • 在我的实验中,如果你将 timeoutInterval 设置为 15 秒,NSURLRequestNSURLSession 是后台会话,iOS 将继续重试大约 15 秒。每 15 秒一次,直到达到 timeoutIntervalForResource。当然,如果 iOS 认为您的网络良好,它就会发生。不会调用回调 - 这是真的。在 iOS 9.2 上测试/
        • @GarySabo:我认为你应该使用可达性模块。
        【解决方案4】:

        作为我对 iOS 7.0.3 的调查,timeoutInterval for NSURLRequest 在与 NSURLSession 一起使用时不会产生任何效果。

        无论您是否将timeoutIntervalForRequest 设置为NSURLSessionConfigurationtimeoutInterval 都会被忽略。

        您可以使用我的小型示例应用程序NetworkTimeoutSample 来检查此行为。

        当你将 'URLReq' 字段设置为 1 时,这会影响 timeoutIntervalNSURLRequest,然后单击 'NSURLSession With URLRequest' 按钮,您的会话将不会出现超时错误。

        如果您想获得与timeoutIntervalNSURLRequest 相同的超时效果,您也可能认识到您应该为NSURLSession 设置timeoutIntervalForResource,而不是timeoutIntervalForRequest

        如果你为NSURLSessionConfiguration设置了timeoutIntervalForRequesttimeoutIntervalForResource的值,较小的值会受到影响(我觉得这种行为与当前的API文档不同)。

        没有关于这些规范的文档,因此可能会在未来的 iOS 版本中进行更改。

        【讨论】:

        • 嗨,您的回答让我朝着正确的方向前进。它让我意识到应该使用 timeoutIntervalForRequest 和 timeoutIntervalForResource。但是,在后台使用 NSURLSessionDownloadTask 时,我似乎看不到在超时延迟后调用任何回调。哪个回调被调用,你得到超时?还是 URLSession:task:didCompleteWithError: 吗?
        • 好吧,好像在不使用后台会话的时候可以使用...但是在使用后台会话的时候就不行了...
        • 我希望我的 Web 服务的超时间隔为 180 秒(3 分钟)。自从我阅读了有关 NSURLSESSION 及其 timeoutIntervalForRequest 和 timeoutIntervalForResource 的信息后,我尝试使用这些,再次产生与 timeOutInterval 相同的结果NSMutableURLRequest.ie,我设置了 180 秒的超时间隔,如 sessionConfig.timeoutIntervalForRequest = 180.0; sessionConfig.timeoutIntervalForResource = 180.0;但我在 75 秒或某个随机时间间隔内收到失败回叫,说“请求超时”。对此有什么想法吗?
        • 我们真的可以只为后台进程设置超时吗?
        • timeoutIntervalForRequest 的定时器在数据到达时被重置,无论有多少数据(只要一个字节到达就会重置它),如果在此时间间隔内绝对没有数据到达,它只会导致超时。 timeoutIntervalForResource 的计时器永远不会重置,除非任务完全完成,否则它会产生超时,因为这将阻止该计时器触发。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-13
        • 1970-01-01
        • 2014-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多