【SwiftUI App】バックグラウンド・フォアグラウンドを検知する【ScenePhase】

今回は、新しいライフサイクルである「SwiftUI App」でバックグラウンドフォアグラウンドを検知する方法についてまとめます。

バックグラウンド・フォアグラウンドを検知する

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

@Environment(\.scenePhase) private var scenePhase

scenePhase は予め EnvironmentValues の一つとして定義されているものです。EnvironmentValues についてはこちらの記事がよく纏められていて参考になるかと思います。

次に onChange イベントを実装し、クロージャ引数の phase の値をチェックします。phase は以下の3つの値のいずれかを取ります。

  • background:バックグラウンド状態を表します。
  • active:フォアグラウンド状態を表します。
  • inactive:バックグラウンド、またはフォアグラウンドになる直前の状態を表します。ちょうどアプリの画面が縮小してアイコンになる最中、またはアイコン状態から拡大して画面が表示される最中にこの状態を取ります。形式上はフォアグラウンドに分類されるようですが、アプリがユーザー入力を受け付けない停止状態であるため、タイマーを動かしている場合などはこのタイミングで停止させるなどの処理を行うと良いでしょう。

以下、サンプルコードです。

@main
struct TestApp: App {
    
    @Environment(\.scenePhase) private var scenePhase
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { phase in
            if phase == .background {
                print("バックグラウンド!")
            }
            if phase == .active {
                print("フォアグラウンド!")
            }
            if phase == .inactive {
                print("バックグラウンドorフォアグラウンド直前")
            }
        }
    }

なお、上記のように Scene で検知するだけでなく、以下のように各Viewでも同様に検知することが出来ます。

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("バックグラウンド!")
            }
            if phase == .active {
                print("フォアグラウンド!")
            }
            if phase == .inactive {
                print("バックグラウンドorフォアグラウンド直前")
            }
        }
    }
}