Как выполнять операции в фоновом режиме, когда приложение 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()

 }

тогда я просто позвонил в этот класс, и вся проблема решена.


пожалуйста, обратитесь к NSURLSessionUploadTask это может вам помочь.


 DispatchQueue.global(qos: .background).async { // sends registration to background queue

 }

вот версия 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.
    }