【问题标题】:Swift | Network call in background thread timing out instantly斯威夫特 |后台线程中的网络调用立即超时
【发布时间】:2021-06-08 22:28:33
【问题描述】:

每当应用程序收到新的静默通知时,我都会配置一个本地网络调用,它会触发 setAction(),它是一个 POST 请求,将与刚刚收到的通知相关的信息发送到我们自己的服务器,在前台,网络调用的工作方式为预期,仅当应用程序处于后台时才会出现问题。我 100% 确定 setAction 正在被调用,但 它看起来像在它启动 dataTask 时网络调用超时,我尝试使用线程,但我不确定问题就在那里。

注意事项:

  • 为了确保不是网络问题,我还尝试了其他 HTTP 请求调用配置

  • 如果我快速发送 2 个静默通知,它会触发 1 个 setAction()

      func application(_ application: UIApplication, didReceiveRemoteNotification         userInfo: [AnyHashable: Any],
                   fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
      // Network call
      tellMe.setAction()
    
      completionHandler(UIBackgroundFetchResult.newData)
    

    }

我已经能够检索到的一些“日志”(真实的 https URL 被隐藏起来,例如)。

Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2103, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <92F80B2F-3D6A-4089-AC76-D160B584712C>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <92F80B2F-3D6A-4089-AC76-D160B584712C>.<1>"
), NSLocalizedDescription=The request timed out., NSErrorFailingURLStringKey=https://actualURL.com, NSErrorFailingURLKey=https://actualURL.com, _kCFStreamErrorDomainKey=4}
The request timed out.

提前谢谢大家,

【问题讨论】:

  • 您在网络请求完成之前呼叫completionHandler。这告诉操作系统可以再次暂停您的应用程序。推迟这个调用,直到你的网络请求完成(但一定要在 30 秒内调用它,否则会发生坏事)。

标签: swift multithreading networking usernotifications


【解决方案1】:

问题在于,completionHandler 在 http 请求甚至有时间被调用之前就被调用了。解决方法是增加更多时间,如下所示(不是最漂亮的实现,但它有效),

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        // Network call
        tellMe.setAction()
        
        let state = UIApplication.shared.applicationState
        if state == .background {
            //print("App in Background")
            DispatchQueue.main.asyncAfter(deadline: .now() + 29) {
                completionHandler(UIBackgroundFetchResult.newData)
            }
        } else {
            //print("App in Foreground or Active")
            completionHandler(UIBackgroundFetchResult.newData)
        }
    }

【讨论】:

  • 您可以避免等待整个 29 秒:创建一个 dispatch_group 并存储它,例如作为应用程序委托的属性。在进行网络调用之前进入组(dispatch_group_enter...),让网络调用在成功或失败时离开调度组,并且 dispatch_group_wait(在 bg 线程上)超时为 29,并调用完成处理程序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
相关资源
最近更新 更多