バックグラウンドとは、アプリ自体起動しているが、画面上に表示されていない状態のことを言います。
対してフォアグラウンドとは、アプリ自体起動していて、今画面上に表示されている状態のことを言います。
このフォアグラウンドとバックグラウンドにアプリがある場合に、何か処理ができたらありがたいですよね。
例えばバックグラウンドだと、アプリが閉じられてしまったり強制終了した時など、データが保存できず、ユーザーが再度アプリを起動しても今まで操作していた内容や入力内容が消えてしまう可能性があります。
ユーザービリティやUXを考える上でも、入力していたデータが消えてしまったりすると、ユーザーの評価にもつながります。
そのため、バックグラウンド処理など特定のシーンで処理をするための実装について、話そうと思います。
▼ 以下にある。バッググラウンドに行った際の処理が。
参照
@Environment(\.scenePhase) private var scenePhase
これはおまじないで、scenePhaseは予約後で、さらにEnvironmentなので全体の環境変数みたいなもの。
sceneを捕捉していて、Sceneプロトコルを継承して、sceneを捕捉しているので、SceneDelegate的なことができるわけで、
それでアプリがバックグラウンドに行ったらsceneの値が変わるので、@Environmentのバインディングによって処理が走る。
これでバッググラウンドに行った際に.onchange(scenePhase)で検知して処理をする。
scenePhaseには、バックグラウンドに行くとその件数にbaskgroundという値が入る。こういう感じでonchangeが検知する
scenePhaseのさまざまな場合
scenePhase | 説明 |
---|---|
active | シーンはフォアグラウンドでインタラクティブです。 |
inactive | シーンはフォアグラウンドにありますが、作業を一時停止する必要があります。 |
background | シーンは現在UIに表示されていません。 |
サンプルコード
今までのUI Kitでアプリのライフサイクルを定義していたSceneDelegate.swiftがなくなり、
今後はSwiftUIではEnvironmentで定義することで、バックグラウンド処理を実装できるようになった。
import SwiftUI @main struct AppMain: App { @UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate @Environment(\.scenePhase) private var scenePhase class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { return true } } var body: some Scene { WindowGroup { ContentView() } .onChange(of:scenePhase){phase in if phase == .background{ print(phase) } else if phase == .inactive{ print(phase) } else { print(phase) } } } } struct ContentView: View { var body: some View { Text("Hello, world!") .padding() } }
@Environment(\.scenePhase) private var scenePhaseを追加。
そしてViewに対して、.onchange配下を追加してます。
.activeで、フォアグラウンドになったらactiveになり、
.backgroundで、バックグラウンドになったらbackgroundになり、
.inactiveで、フォアグラウンドからバックグラウンドになる間で、バックグラウンドからフォアグラウンドになる間で、inactiveになる。
以下で、ビルドした結果を確認してみる。
ビルドしてアプリを起動すると、active
バックグラウンドに移そうとすると、inactiveになって最終的にbackgroundになっている。
そしてまたアプリの画面を開くと、inactiveになってからactiveになっているのが確認できる。
import SwiftUI @main struct AppMain: App { @UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { return true } } var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @Environment(\.scenePhase) private var scenePhase var body: some View { TabView{ Text("Hello, world!") .tabItem { Image(systemName: "house") Text("Home").font(/*@START_MENU_TOKEN@*/.largeTitle/*@END_MENU_TOKEN@*/) } Text("Hello, world2!") .tabItem { Image(systemName: "house") Text("Home1").font(/*@START_MENU_TOKEN@*/.largeTitle/*@END_MENU_TOKEN@*/) } .onChange(of:scenePhase){phase in if phase == .background{ print(phase) } else if phase == .inactive{ print(phase) } else { print(phase) } } } } }