Как выполнять операции в фоновом режиме, когда приложение iOS находится на переднем плане
У меня есть файл JSON, заполненный строковыми данными в каталоге документов. В пользовательском интерфейсе приложения есть UIButton. При нажатии кнопки в файл JSON добавляется новая строка.
теперь я ищу любую службу iOS, которая поможет мне отправить эти строки (из файла JSON) на сервер с помощью swift. И этот сервис должен быть полностью независим от моего кода. Дело в том, что когда я нажимаю UIButton, первый шаг-строка сохраняется в файл JSON, тогда служба должна возьмите эту строку и отправьте ее на сервер, если интернет доступен.
когда строка отправлена успешно, она должна быть удалена из файла JSON. Эта служба должна отслеживать каждые 30 секунд, если есть какая-либо строка, сохраненная в файле JSON, а затем отправить ее на сервер.
я погуглил и нашел выборки фона но он запускает performFetchWithCompletionHandler
функция автоматически, и я не могу знать, когда iOS запускает его. Я хочу, чтобы вызвать этот вид обслуживания себя после каждых 30 считанные секунды.
5 ответов
обзор Фоновый часть руководства по программированию приложений Apple для iOS.
UIApplication
предоставляет интерфейс для запуска и завершения фоновых задач с UIBackgroundTaskIdentifier
.
в верхнем уровне вашего AppDelegate
, создайте идентификатор задачи уровня класса:
var backgroundTask = UIBackgroundTaskInvalid
Теперь создайте свою задачу с операцией, которую вы хотите завершить, и реализуйте случай ошибки, когда ваша задача не была завершена до истечения срока ее действия:
backgroundTask = application.beginBackgroundTaskWithName("MyBackgroundTask") {
// This expirationHandler is called when your task expired
// Cleanup the task here, remove objects from memory, etc
application.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
}
// Implement the operation of your task as background task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// Begin your upload and clean up JSON
// NSURLSession, AlamoFire, etc
// On completion, end your task
application.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
}
то, что я сделал, я просто использую подход, обсуждаемый JAL выше.
эти три метода, которые я использовал
func reinstateBackgroundTask() {
if updateTimer != nil && (backgroundTask == UIBackgroundTaskInvalid) {
registerBackgroundTask()
}
}
func registerBackgroundTask() {
backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
[unowned self] in
self.endBackgroundTask()
}
assert(backgroundTask != UIBackgroundTaskInvalid)
}
func endBackgroundTask() {
NSLog("Background task ended.")
UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
здесь updateTimer
типа NSTIMER
класс
Вышеуказанные функции находятся в моем собственном созданном классе с именем "syncService"
Этот класс имеет инициализатор, который является
init(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.reinstateBackgroundTask), name: UIApplicationDidBecomeActiveNotification, object: nil)
updateTimer = NSTimer.scheduledTimerWithTimeInterval(30.0, target: self, selector: #selector(self.syncAudit), userInfo: nil, repeats: true)
registerBackgroundTask()
}
тогда я просто позвонил в этот класс, и вся проблема решена.
вот версия swift 4 ответа от JAL
extension UIApplication {
/// Run a block in background after app resigns activity
public func runInBackground(_ closure: @escaping () -> Void, expirationHandler: (() -> Void)? = nil) {
DispatchQueue.main.async {
let taskID: UIBackgroundTaskIdentifier
if let expirationHandler = expirationHandler {
taskID = self.beginBackgroundTask(expirationHandler: expirationHandler)
} else {
taskID = self.beginBackgroundTask(expirationHandler: { })
}
closure()
self.endBackgroundTask(taskID)
}
}
}
Пример Использования
UIApplication.shared.runInBackground({
//do task here
}) {
// task after expiration.
}