web-dev-qa-db-ja.com

iOSアプリケーションがフォアグラウンドにあるときにバックグラウンドで操作を実行する方法

DocumentsDirectoryに文字列データが入力されたJSONファイルがあります。アプリケーションのユーザーインターフェイスには、UIButtonがあります。ボタンを押すと、新しい文字列がJSONファイルに追加されます。

現在、Swiftを使用してこれらの文字列を(JSONファイルから)サーバーに送信するのに役立つiOSサービスを探しています。そして、このサービスは私のコードから完全に独立している必要があります。重要なのは、UIButtonを押すと、最初のステップは文字列がJSONファイルに保存され、インターネットが利用可能な場合はサービスがこの文字列を取得してサーバーに送信することです。

文字列が正常に送信されたら、JSONファイルから削除する必要があります。このサービスは、JSONファイルに文字列が保存されているかどうかを30秒ごとに追跡し、サーバーに送信する必要があります。

Googleで検索して バックグラウンドフェッチ を見つけましたが、performFetchWithCompletionHandler関数が自動的にトリガーされ、iOSがいつトリガーするかわかりません。この種のサービスを30秒ごとに自分でトリガーしたいと思います。

11
user3314286

IOS用Appleのアプリプログラミングガイドの バックグラウンド実行 の部分を確認してください。

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
}
11
JAL

私がやったことは、上記のJALで説明したアプローチを使用することです。

これらは私が使用した3つの方法でした

    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()

 }

次に、このクラスを呼び出すだけで、問題全体が解決されます。

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

 }
1
Aditya Sharma

NSURLSessionUploadTaskを参照してください。

1
Kiran K

これがSwift JALによる回答の4バージョンです

  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.
    }
0
levin varghese