I am struggling with something that seems like it should work but doesn't, and I'm not sure whether to submit a bug.
The use case is having an app where its state can be passed in from the environment, and therefore I can do basic testing of the navigation and function of the app before introducing the actual data layer, which will be from an NSPersistentCloudKitContainer.
The basic implementation of the environment value is:
extension EnvironmentValues {
@Entry var appState: some AppState = MockAppState()
}
protocol AppState {}
@Observable
class MockAppState: AppState {}
Providing a default value for appState does not cause an issue, but if I try to inject the MockAppState into the environment of the ContentView, I get an error:
import SwiftUI
@main
struct CascadingPoetryCircles240926App: App {
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.appState, MockAppState())
/*
Error: Cannot convert value of type 'MockAppState' to expected argument type 'some AppState'
*/
}
}
}
I am able to pass it to the contentView directly without an error:
@main
struct CascadingPoetryCircles240926App: App {
var body: some Scene {
WindowGroup {
ContentView(appState: MockAppState())
}
}
}
...
struct ContentView<ViewAppState: AppState>: View {
var appState: ViewAppState
var body: some View {
VStack {}
}
}
I will proceed with that strategy for now, but this feels like a common use case for @Environment, but in this case we lose the handiness of keeping the appState in the environment without having to pass it view to view. I suspect I am missing some basic issue about Opaque types, but would be grateful if anyone has the patience to help me understand the reason for the different function of the environment variable.