首页 > 解决方案 > 应用程序中的 Alamofire 请求移至后台。连接丢失

问题描述

当应用程序进入后台时,它想发出一个请求,不幸的是它收到了错误:

sessionTaskFailed (error: Error Domain = NSURLErrorDomain Code = -1005 "The network connection was lost...")

代码:

override func viewDidLoad() {
        super.viewDidLoad()
    notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}


@objc func appMovedToBackground() {

let URL: String = "http://www.test.com/"
AF.request(URL, method: .post, parameters: parameters, headers: headers)
  .responseJSON { [] response in
                                
  switch response.result {
   case .success(let data):
     print(data)
   case .failure(let error):
     print(error)
   }
 }

}

标签: swiftxcode

解决方案


看起来你应该实现后台任务。Apple文档提供了一个如何执行此操作的示例:

func sendDataToServer( data : NSData ) {
   // Perform the task on a background queue.
   DispatchQueue.global().async {
      // Request the task assertion and save the ID.
      self.backgroundTaskID = UIApplication.shared.
                 beginBackgroundTask (withName: "Finish Network Tasks") {
         // End the task if time expires.
         UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
         self.backgroundTaskID = UIBackgroundTaskInvalid
      }
            
      // Send the data synchronously.
      self.sendAppDataToServer( data: data)
            
      // End the task assertion.
      UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
      self.backgroundTaskID = UIBackgroundTaskInvalid
   }
}

编辑

我没有编译此代码,但根据 Apple文档,可以这样做:

final class ViewControler: UIViewController {
    
    private var backgroundTaskID: UIBackgroundTaskIdentifier?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if #available(iOS 13.0, *) {
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(willResignActive),
                                                   name: UIScene.willDeactivateNotification,
                                                   object: nil)
        } else {
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(willResignActive),
                                                   name: UIApplication.willResignActiveNotification,
                                                   object: nil)
        }
    }
    
    @objc func willResignActive(_ notification: Notification) {
        // Perform the task on a background queue.
        DispatchQueue.global().async {
            // Request the task assertion and save the ID.
            self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish Network Tasks") {
                // End the task if time expires.
                UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
                self.backgroundTaskID = .invalid
            }
            
            self.sendRequest()
        }
    }
    
    func sendRequest() {
        let URL: String = "http://www.test.com/"
        AF.request(URL, method: .post, parameters: parameters, headers: headers)
            .responseJSON { [unowned self] response in
                
            // End the task assertion.
            UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
            self.backgroundTaskID = .invalid
            
            switch response.result {
            case .success(let data):
                print(data)
            case .failure(let error):
                print(error)
            }
        }
    }
}

在这段代码中,我们订阅了应用程序 进入后台时的通知,并创建了一个后台任务在后台任务中,我们执行一个必要的请求。如果此请求在响应闭包中执行速度超过 5 秒,我们会使我们的后台任务无效并完成它的工作。如果请求执行时间超过 5 秒,则后台任务终止。


推荐阅读