Upon further review, reintroducing the value into the environment seems to work for some parts of my view hierarchy but not others. However, passing by a parameter works for all my views (thus far).
There's some pretty weird stuff I see when I try to figure out what's happening with the environment. I assume the problem is that I don't fully understand how the Environment works and maybe side-effects that certain code has on Environment values...
As an example of some of the weirdness I see... here's a simplified version of my code (target is Apple Watch):
import SwiftUI
struct ContentView: View {
@Environment(\.scenePhase) var scenePhase
var body: some View {
Child(paramScenePhase: scenePhase)
}
}
struct Child: View {
var paramScenePhase: ScenePhase
var body: some View {
ChildButton(paramScenePhase: paramScenePhase)
}
}
struct ChildButton: View {
var paramScenePhase: ScenePhase
@State private var isPresentingProblemView: Bool = false
var body: some View {
Button("Press me") {
isPresentingProblemView = true
}
.sheet(isPresented: $isPresentingProblemView) {
ProblemView(paramScenePhase: paramScenePhase)
}
}
}
struct ProblemView: View {
@Environment(\.scenePhase) var enviroScenePhase
var paramScenePhase: ScenePhase
var body: some View {
Text("Hi")
.onChange(of: enviroScenePhase) { phase in
print("enviroScenePhase " + scenePhaseString(phase))
}
.onChange(of: paramScenePhase) { phase in
print("paramScenePhase " + scenePhaseString(phase))
}
}
}
func scenePhaseString(_ phase: ScenePhase) -> String {
switch(phase) {
case .active:
return "phase: ACTIVE"
case .inactive:
return "phase: INACTIVE"
case .background:
return "phase: BACKGROUND"
default:
return "phase: UNKNOWN"
}
}
When I run this simplified code in the simulator, press the "Press me" button, and then press the "always on" button in the watch simulator twice (to go inactive and then active again), I get the following in the console (and this is the expected behavior):
enviroScenePhase phase: INACTIVE
paramScenePhase phase: INACTIVE
enviroScenePhase phase: ACTIVE
paramScenePhase phase: ACTIVE
I then commented out var paramScenePhase: ScenePhase within ProblemView (and then comment out only the other parts of the code to get rid of compilation errors). Running the same experiment, this is what I get in the console:
enviroScenePhase phase: INACTIVE
This is not the expected behavior. And that's all I see no matter how many times I press the always-on button to toggle between inactive and active phases.
If I then comment out var paramScenePhase: ScenePhase in the ChildButton view (and change the ChildButton instantiation to ChildButton()), then nothing prints to the console at all no matter how many times I press the always-on simulator button.
I just don't understand how changing what parameters are used in a view also changes the behavior of an environment variable.
Topic:
App & System Services
SubTopic:
Core OS
Tags: