Background Task: 主要な概念、タスクの登録とバックグラウンド実行

著者: IT Sectr 公開日: 2026-03-27 読了時間: 10 分

Background Taskは、アプリケーションがバックグラウンドに移行した後に操作を完了できるようにするiOSの仕組みです。システムはタスクの実行に制限時間(最大30秒)を割り当て、それを過ぎるとアプリケーションは強制的に中断されます。Apple(2026年)によると、 expiration handlerの使用はバックグラウンドタスクを正しく完了するための必須要件です。

重要ポイント

  • Background Task — アプリがバックグラウンドに入った後に操作を完了するためのiOSメカニズム。
  • beginBackgroundTask — バックグラウンドタスクを登録するためのUIApplicationの主要メソッド。
  • Expiration handler — 割り当てられた時間が切れたときにシステムによって呼び出されるコードブロック。
  • 30秒の制限 — 標準の実行時間。Background Modesで延長可能。
  • UIApplication.shared.endBackgroundTask — タスクを正しく完了するための必須の呼び出し。

iOSのBackground Taskとは?

Background Taskは、アプリケーションがバックグラウンドに移行した後に実行時間を延長できるようにするプログラム可能なiOSメカニズムです。ユーザーがアプリを最小化すると、システムはUIApplicationDelegate.applicationDidEnterBackgroundを呼び出します。その時点で重要な操作(データの保存、リクエストの送信)が実行中の場合は、アプリケーションはbeginBackgroundTaskを介して追加の時間を要求できます。

Background Tasksが必要な理由

Background Taskを使用しない場合、アプリケーションはバックグラウンドに入ってから3~5秒以内に強制的に中断されます。未完了の操作はすべて中断され、データは保存されず、ネットワークリクエストは中断され、状態は失われます。Background Taskは、これらの操作を正しく完了するために最大30秒の時間をアプリケーションに提供します。

  • 状態の保存 — CoreData、UserDefaults、またはファイルシステムへのデータ書き込み。
  • ネットワークリクエストの完了 — サーバーの応答を待ち、結果を処理。
  • 分析データの送信 — 中断前に分析サーバーにイベントを送信。
  • リソースのクリーンアップ — ファイル記述子のクローズ、メモリ解放。
  • キャッシュ — 次回起動時に復元するための中間結果の書き込み。

歴史と進化

beginBackgroundTaskは、マルチタスクをサポートする最初のリリースであるiOS 4.0で登場しました。iOS 4以前は、ホームボタンを押すとアプリケーションは完全に終了していました。iOS 7ではBackground FetchとURLSessionのバックグラウンド設定が導入されました。iOS 13以降、Appleは新しいプロジェクトにBGTaskSchedulerを推奨していますが、beginBackgroundTaskは短期間の操作に引き続き有用です。

beginBackgroundTaskの仕組み:ライフサイクル

beginBackgroundTaskは、タスクを登録して一意のUIBackgroundTaskIdentifierを返すUIApplicationのメソッドです。システムはバックグラウンド実行タイマーを増やします。時間が切れるとexpiration handlerが呼び出され、その後アプリケーションはendBackgroundTask(identifier:)を呼び出してタスクを正しく完了する必要があります。

ステップバイステップの実行プロセス

ステップ1 — アプリケーションがdidEnterBackground通知を受け取ります。ステップ2 — beginBackgroundTask(expirationHandler:)が呼び出されます。ステップ3 — 重要な操作(保存、ネットワークリクエスト)が実行されます。ステップ4 — 完了時にendBackgroundTask(identifier:)が呼び出されます。操作が30秒以内に完了しない場合、システムはexpiration handlerを呼び出し、アプリケーションは直ちにタスクを終了する必要があります。

swift
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

func startBackgroundTask() {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Expiration handler
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

func finishBackgroundTask() {
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

UIApplication.shared.backgroundTimeRemaining

backgroundTimeRemainingプロパティは、バックグラウンドタスクが強制終了されるまでの残り秒数を返します。値はリアルタイムで減少します。アプリケーションがバックグラウンドにない場合はDBL_MAXを返します。このプロパティを使用して動作を適応させます:残り5秒未満になったら、長時間の操作を中断して進捗を保存します。

複数タスク

アプリケーションは複数のBackground Tasksを同時に登録できます。各タスクは独自の識別子を取得します。合計実行時間は累積されます — 3つのタスクが登録されている場合、アプリケーションは最大90秒を取得できます。ただし、リソースが枯渇したりバッテリーの制限を超えた場合、システムはアプリケーションを途中で終了することがあります。

Expiration handler:必須の完了処理

Expiration handlerは、バックグラウンドタスクに割り当てられた時間が切れたときにシステムが呼び出すコードブロックです。expiration handlerを持つことはAppleの必須要件です。これがないと、アプリケーションはシステムによって強制終了され、データが失われる可能性があります。

Expiration handlerに含めるべきもの

expiration handlerは、アプリケーションの状態を保存するための最小限のアクションを実行する必要があります:現在のデータを永続ストレージに保存し、対応する識別子でendBackgroundTaskを呼び出し、識別子を.invalidに設定します。expiration handler内で新しい長時間の操作を開始することは禁止されています — 実行時間は1~2秒に制限されています。

swift
func handleExpiration() {
    // 実行進捗を保存中
    saveProgressToUserDefaults()

    // アクティブなネットワークリクエストをキャンセル中
    currentTask?.cancel()

    // Background Taskを終了中
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

// Expiration handler付き登録
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
    withName: "SaveDocument",
    expirationHandler: handleExpiration
)

Expiration handlerの一般的なエラー

最も一般的な間違いは、expiration handler内でendBackgroundTaskを呼び出さないことです。この場合、システムはタスクをアクティブと見なし続け、アプリケーションは中断状態に移行せず、バッテリーを消耗します。2つ目の間違いは、expiration handler内で長時間の操作を開始することです。システムは操作が完了する前にアプリケーションを終了する可能性があり、データが失われます。

残り時間の確認

expiration handlerでは、実行時間は極めて限られています — 通常1秒未満です。したがって、handler内では以下を実行できません:複雑な計算、ネットワークリクエスト、CoreDataへの大量データの書き込み。アトミックな操作のみ:UserDefaultsへの単一キーの書き込み、状態フラグの設定、endBackgroundTaskの呼び出し。

SwiftでのBackground Taskコード例

アプリケーションがバックグラウンドに入ったときにドキュメントを保存するための完全なBackground Task実装を見てみましょう。この例には、タスクの登録、残り時間の確認を伴う操作の実行、endBackgroundTaskによる適切な完了が含まれています。

進捗を表示してドキュメントを保存

バックグラウンドに入るとき、アプリケーションは大きなドキュメントの保存を開始します。Background Taskは操作に最大30秒を提供します。時間が切れると、expiration handlerが中間結果を保存します。保存が完了すると、リソースを解放するためにendBackgroundTaskが呼び出されます。

swift
class DocumentManager {
    private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    func saveDocumentInBackground(document: Document) {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask {
            self.saveProgress(document)
            self.endBackgroundTask()
        }

        DispatchQueue.global().async {
            document.save()
            self.endBackgroundTask()
        }
    }

    private func endBackgroundTask() {
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

サーバーへのデータ送信

バックグラウンドでのネットワークリクエストは特別な注意が必要です — expiration handlerが応答を受信する前にリクエストを中断する可能性があります。dataTaskを伴うURLSessionを使用し、送信前にbackgroundTimeRemainingを確認してください。残り5秒未満の場合は、次のアプリ起動まで送信を延期してください。

swift
func sendCriticalData(data: Data) {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // 再送信用のデータを保存中
        saveForRetry(data)
        self.endBackgroundTask()
    }

    let task = URLSession.shared.dataTask(with: request) { _, _, error in
        if error != nil {
            saveForRetry(data)
        }
        self.endBackgroundTask()
    }
    task.resume()
}

残り時間の監視

長時間の操作では、UIApplication.shared.backgroundTimeRemainingを監視してください。値がしきい値(10秒)を下回ったら、現在の操作を中断して中間結果の保存を開始します。これにより、expiration handlerが強制的に呼び出される前に適切に完了できます。

Background Task使用のベストプラクティス

Background Taskは強力なメカニズムですが、不適切に使用するとバッテリーやパフォーマンスの問題を引き起こします。Appleの推奨事項とコミュニティで実証されたプラクティスに従うことで、一般的な間違いを回避し、安定したアプリケーション動作を確保できます。

実行時間の最小化

Background Taskをできるだけ早く完了してください。バックグラウンド実行の1秒ごとにバッテリーを消費します。最適な時間 — 5秒未満。操作にそれ以上かかる場合は、BGTaskSchedulerまたはBackground Modesの使用を検討してください。実際の必要性なくbeginBackgroundTask呼び出しで人為的にタスクを延長しないでください。

識別子の適切な使用

UIBackgroundTaskIdentifierはクラスまたは構造体のプロパティとして保存してください。グローバル変数として渡さないでください — 複数タスクで競合を引き起こします。endBackgroundTaskを呼び出した後、識別子を.invalidに設定して二重完了を防止してください。

Background Taskのテスト

Xcode Simulatorで、ホームボタン(Command + Shift + H)でアプリをバックグラウンドに切り替えます。Debug — Simulate Background Fetchを使用してバックグラウンド起動をテストします。時間切れをシミュレートするには、環境変数BACKGROUND_TASK_SIMULATE_EXPIRATION = YESを設定します — expiration handlerが5秒以内に呼び出されます。

swift
// 操作開始前の残り時間を確認中
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
    // 時間不足 — タスクを延期
    scheduleForNextLaunch()
    return
}

// 時間管理による操作の実行
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
    saveProgress()
    self.endBackgroundTask()
}

Retainサイクルの回避

expiration handlerはselfをキャプチャします — backgroundTaskIDが同じオブジェクトのプロパティとして保存されている場合、retainサイクルが発生する可能性があります。クロージャで[weak self]を使用するか、識別子を個別に保存してください。retainサイクルはメモリリークを引き起こし、アプリケーションが終了するまでオブジェクトが解放されません。

Background Task vs BGTaskScheduler:アプローチ比較

iOS 13のリリースに伴い、AppleはBGTaskSchedulerを導入しました — 古いBackground Task APIに代わる最新のものです。どちらのメカニズムも同様のタスクを解決しますが、BGTaskSchedulerはより多くの制御と柔軟性を提供します。違いを理解することで、特定のシナリオに適したツールを選択するのに役立ちます。

特性Background TaskBGTaskScheduler
iOSバージョン4.0+13.0+
最大時間30秒30秒 / 10分(processing)
開始didEnterBackgroundスケジューリング + システム
実行保証バックグラウンド移行時のみシステムの都合の良い任意の時間
Expiration handlerあり、必須あり、task.expirationHandler経由
インターネット起動時に必要requiresNetworkConnectivityで利用可能
充電不要processingではオプション

Background Taskを使用する場合

beginBackgroundTaskは、バックグラウンドに入るときに即座に実行する必要がある短期間の操作に適しています:状態の保存、ネットワークリクエストの完了、データのキャッシュ。APIはシンプルで、Info.plistの設定や識別子の登録は不要です。10秒未満で完了する操作に最適です。

BGTaskSchedulerを使用する場合

BGTaskSchedulerは、任意の都合の良い時間に実行できるタスクに適しています:定期的な同期、キャッシュのクリーンアップ、ウィジェットの更新。システム自体がユーザーの行動とバッテリー状態を考慮して最適な時間を選択します。長時間の操作(最大10分)にはBGProcessingTaskを使用してください。

併用

両方のAPIを同じアプリケーションで使用できます。Background Task — バックグラウンドに入るときの即時操作(下書きの保存)に。BGTaskScheduler — スケジュールされた更新(6時間ごとの同期)に。責任を分離することで、データの適切な保存とエネルギー効率の良いバックグラウンドメンテナンスを保証します。

よくある質問

didEnterBackgroundの外部でbeginBackgroundTaskを呼び出せますか?

はい、beginBackgroundTaskはアプリケーション実行中の任意の時点で呼び出すことができます。ただし、システムの時間割り当てはバックグラウンドに移行した後にのみ開始されます。アプリケーションがフォアグラウンドにある場合、beginBackgroundTaskを呼び出しても効果はありません — backgroundTimeRemainingはDBL_MAXを返し、タスクはバックグラウンドに入ったときにアクティブになります。

endBackgroundTaskを呼び出さないとどうなりますか?

endBackgroundTaskが呼び出されない場合、システムはアプリケーションをバックグラウンドでアクティブと見なし続けます。30秒後にexpiration handlerが呼び出されますが、それにもendBackgroundTaskがない場合、アプリケーションはメモリに残り続け、バッテリーを消耗します。iOS 13+では、システムは3分後にそのようなアプリケーションを強制終了します。

Background Taskを30秒以上延長するには?

標準時間は30秒です。延長できるのはBackground Modes:オーディオ(再生)、位置情報(GPS)、Bluetooth(BLE)を介してのみです。またはBGProcessingTask(iOS 13+) — 充電とWi-Fi環境で最大10分まで。beginBackgroundTask自体には制限を増やす方法はありません。

Background TaskはiPadで動作しますか?

はい、iPadOSはiOSと同じ制限でbeginBackgroundTaskを完全にサポートしています。Stage Managerを搭載したiPadでは、アプリケーションはメモリに長く留まることができます — システムはRAMが多いためアプリケーションを中断する頻度が低くなります。ただし、バックグラウンドタスクの30秒制限は変わりません。

実機でBackground Taskをデバッグするには?

デバイスをXcodeに接続し、アプリケーションを起動して最小化すると、コンソールにシステムログが表示されます。sysdiagnoseを使用して詳細なログを収集します:デバイスからsysdiagnoseを強制トリガーします(音量上 + 音量下 + 電源)。XcodeのDebug Navigatorでバックグラウンドタスクのアクティビティを監視します。

まとめ

  • Background Task — iOS 4.0以降で利用可能な、バックグラウンド移行後に操作を完了するためのiOSメカニズム。
  • beginBackgroundTask — タスクを登録し、その完了のための識別子を返すUIApplicationメソッド。
  • Expiration handler — 30秒の制限が切れたときにシステムによって呼び出される必須のコードブロック。
  • endBackgroundTask — タスクを正しく完了するための必須の呼び出し。これがないとアプリケーションはメモリに残り続ける。
  • BGTaskScheduler — スケジューリング、2つのタスクタイプ、実行条件を備えた最新の代替手段(iOS 13+)。
  • backgroundTimeRemaining — 残り時間を確認し、タスクの動作を適応させるためのプロパティ。
  • 即時の短期間操作にはBackground Taskを、新しいプロジェクトでのスケジュールされたバックグラウンド更新にはBGTaskSchedulerを使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください