swift - 应用程序中的 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)
}
}
}
解决方案
看起来你应该实现后台任务。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 秒,则后台任务终止。
推荐阅读
- python - selenium wedriver程序无法继续
- django - 在 QuerySet 中的所有对象中递增特定参数
- awk - 如果 awk 从处理表达式返回 null,如何返回 0?
- swift - 授权标头在使用 Swift 的请求中消失
- sql - Azure 数据工厂 V2 复制数据问题 - 错误代码:2200 已添加具有相同密钥的项目
- php - PHP 正在我的表中创建两行,一行可以,但额外空
- python - 在 groupby 之后来自 nunique 的奇怪输出
- javascript - javascript:如何在 for 循环中使用 javascript 数组
- c++ - 我们可以在 c++ 代码中使用像 coremotion 这样的 iOS 框架吗
- javafx - 程序启动方法中的 Javafx 异常