😇

【iOS】フォアグラウンド状態を検知する際のScenePhaseとonChange(of:)のハマりポイント

2023/04/05に公開

アプリの状態がフォアグラウンド、バックグラウンドになっているを検知する時にScenePhaseonChange(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を入力してみます。

結果

textnewValueの値ともに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
}

textprintログは空文字になっており、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
}

おわりに

アプリのフォアグラウンド、バックグラウンド状態を検知する為にScenePhaseonChange(of:)を組みあわえて使用する際は、newValueの値を使用して分岐させる必要がありますので注意しましょう。

というか、基本的にはnewValue側の値を使用するように心がけたいと思います。

lilossa-banner

参考

https://developer.apple.com/documentation/swiftui/view/onchange(of:perform:)

Discussion