I have a custom environment key defined:
struct MyCustomKey: EnvironmentKey {
static let defaultValue = MyCustom.dummy
}
extension EnvironmentValues {
var myCustom: MyCustom {
get { self[MyCustomKey.self] }
set { self[MyCustomKey.self] = newValue }
}
}
and pass it on the top level:
let myCustomInstance = MyCustom()
@main
struct ThygeApp: App {
var body: some Scene {
WindowGroup {
MainWindow()
.environment(\.myCustom, myCustomInstance)
}
}
}
I really do not want it to use the default instance ever, I want it to be specified explicitly.
Is there a way to have it fail on use if it is not specified in the environment? I have made it so that the .dummy
instance does a fatalError()
and that works so far as it halt the app. But there are no hints in the stack track as to where the offending code is - where do I use the environment value without passing it like I do here
.environment(\.myCustom, myCustomInstance)
The only solution to find the offending use is to add an assert()
to all func
defined in MyCustom
. That seems cumbersome and error prone.
Is there another way?
@nicolai One way is to use an Environment
to get an observable object from a view’s environment, Get an observable object article has literature about this.
Basically with this approach, you must set the object in the environment using the the object itself or a key path.
@Observable
class Library {
var books: [Book] = [Book(), Book(), Book()]
var availableBooksCount: Int {
books.filter(\.isAvailable).count
}
}
@main
struct BookReaderApp: App {
@State private var library = Library()
var body: some Scene {
WindowGroup {
LibraryView()
.environment(library)
}
}
}
struct LibraryView: View {
@Environment(Library.self) private var library
var body: some View {
// ...
}
}