#swift #xcode
Вопрос:
Когда приложение переходит в фоновый режим, оно хочет сделать один запрос, к сожалению, оно получает сообщение об ошибке:
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)
}
}
}
Ответ №1:
Похоже, вам следует реализовать фоновую задачу. В документации 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 секунд, фоновая задача завершается.
Комментарии:
1. Вопрос в том, как это сделать, когда запрос iAF является асинхронным. У меня мало запросов в цикле.
2. @tomtript Я обновил свой ответ