DocumentsDirectoryに文字列データが入力されたJSONファイルがあります。アプリケーションのユーザーインターフェイスには、UIButtonがあります。ボタンを押すと、新しい文字列がJSONファイルに追加されます。
現在、Swiftを使用してこれらの文字列を(JSONファイルから)サーバーに送信するのに役立つiOSサービスを探しています。そして、このサービスは私のコードから完全に独立している必要があります。重要なのは、UIButtonを押すと、最初のステップは文字列がJSONファイルに保存され、インターネットが利用可能な場合はサービスがこの文字列を取得してサーバーに送信することです。
文字列が正常に送信されたら、JSONファイルから削除する必要があります。このサービスは、JSONファイルに文字列が保存されているかどうかを30秒ごとに追跡し、サーバーに送信する必要があります。
Googleで検索して バックグラウンドフェッチ を見つけましたが、performFetchWithCompletionHandler
関数が自動的にトリガーされ、iOSがいつトリガーするかわかりません。この種のサービスを30秒ごとに自分でトリガーしたいと思います。
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
}
私がやったことは、上記の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()
}
次に、このクラスを呼び出すだけで、問題全体が解決されます。
DispatchQueue.global(qos: .background).async { // sends registration to background queue
}
NSURLSessionUploadTaskを参照してください。
これが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.
}