今回作成するアプリ

アプリを作っていると、アプリがバックグランド移ったときやフォアグラウンドに戻ったときなどを検知したい場合があります。

例えばタイマーアプリでバックグランドに移ったら時計を止めるなどです。

今回はSwiftUIでバックグラウンド・フォアグラウンドを検知する方法をご紹介します。

実装

コード

import SwiftUI

struct ContentView: View {
    
    @Environment(\.scenePhase) private var scenePhase
    
    var body: some View {
        VStack {
            Text("Hello, world!")
        }
        .onChange(of: scenePhase) { phase in
            if phase == .background {
                print("バックグラウンド(.background)")
            }
            if phase == .active {
                print("フォアグラウンド(.active)")
            }
            if phase == .inactive {
                print("バックグラウンドorフォアグラウンド直前(.inactive)")
            }
        }
    }
}

出力結果

バックグラウンドorフォアグラウンド直前(.inactive)
フォアグラウンド(.active)
バックグラウンドorフォアグラウンド直前(.inactive)
バックグラウンド(.background)

解説

まず最初に、環境変数の scenePhase を宣言します。

scenePhase は予め EnvironmentValues の一つとして定義されているものです。

次に onChange イベントを実装し、クロージャ引数の phase の値をチェックします。

phaseの値は、Active, Inactive, Backgroundの3つの値をとります(ActiveとBackgroundだけではありません)。
下の状態遷移図を見るとわかりやすいかもしれません。

起動するときはInactiveを経由してからActiveになり、ActiveからBackgroundになるときもInactiveを経由します。

つまり、Inactive → Active → Inactive → Background のように起動状態は変化するのです。

print文の出力結果は、下の動画にようにホーム画面からアプリを起動しホーム画面に戻るまでのPhaseの変化を表しています。

状態内容
Unattachedアプリが未起動の状態。
Backgroundアプリがバックグラウンドで実行中。
Foreground Inactiveアプリがフォアグラウンドで実行中だが、イベントは受信していない。別の状態に切り替わる時に、一瞬この状態になる。
Foreground Activeアプリがフォアグラウンドで実行中。アプリを使用している時は基本的にこの状態。
Suspendedアプリがバックグラウンドで未実行。

https://qiita.com/yutosa3/items/89d6295196d24965bb49 より引用

動作

環境

macOS Ventura 13.2.1

Xcode 14.2

iOS 16.2

Simulater iPhone 14 Pro Max

アイキャッチ画像 出典: App.com