😇
【iOS】フォアグラウンド状態を検知する際のScenePhaseとonChange(of:)のハマりポイント
アプリの状態がフォアグラウンド、バックグラウンドになっているを検知する時にScenePhaseとonChange(of:)を使用して状態の変化をみることがあると思うのですが、少しハマってしまったのでハマったポイントを共有しておきたいと思います。
環境
- Xcode 14.2
- iOS 16.2
@StateとonChangeの場合
下記のコードで試してみます。
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack {
TextField("Input Text here..", text: $text)
Divider()
}
.padding()
.onChange(of: text) { newValue in
print("text", text)
print("newValue", newValue)
}
}
}
TexFieldに1を入力してみます。

結果
textとnewValueの値ともに1という新しい値になっているのを確認出来ました。
.onChange(of: text) { newValue in
print("text", text) // text 1
print("newValue", newValue) // newValue 1
}
新旧の値を確認する方法
下記のような記述にすることで、変わる前の値と変わった後の値を検知できます。
出力結果は、上記と同じようにTextFieldに1を入力した際の出力例です。
.onChange(of: text) { [text] newValue in
print("text", text) // text
print("newValue", newValue) // newValue 1
}
textのprintログは空文字になっており、1が入力される前の値を取得できています。
SceneStateとonChangeの場合
下記のコードで試してみます。
struct ContentView: View {
@Environment(\.scenePhase) var scenePhase
var body: some View {
Text("ScenePhace")
.onChange(of: scenePhase) { newValue in
print("scenePhase", scenePhase)
print("newValue", newValue)
}
}
}
結果
アプリを起動した際の出力結果です。
.onChange(of: scenePhase) { newValue in
print("scenePhase", scenePhase) // scenePhase inactive
print("newValue", newValue) // newValue active
}
scenePhaseの出力が状態が変わる前の値inactiveになっています。
ScenePhaseの場合、デフォルトで新旧の値を確認する方法で試したような状態になっているようです。
下記のようなコードに変更して、出力結果を確認しても結果は同じでした。
.onChange(of: scenePhase) { [scenePhase] newValue in
print("scenePhase", scenePhase) // scenePhase inactive
print("newValue", newValue) // newValue active
}
おわりに
アプリのフォアグラウンド、バックグラウンド状態を検知する為にScenePhaseとonChange(of:)を組みあわえて使用する際は、newValueの値を使用して分岐させる必要がありますので注意しましょう。
というか、基本的にはnewValue側の値を使用するように心がけたいと思います。

参考
Discussion