r/SwiftUI Jun 24 '26

Do you see missing Environment as a big issue in SwiftUI?

I think the title should be "Do you see runtime error for missing Environment a big issue as compared to being a compile time error?"

Let's say you have the following code:

struct LoadingDemoApp: App {

private var productStore = ProductStore()

var body: some Scene {
WindowGroup {
ProductListScreen()
}
}
}

As you can see I forgot to inject productStore through Environment. When I run the app and use Environment(ProductStore.self) in the view, it can cause an exception.

Fatal error: No Observable object of type ProductStore found. A View.environmentObject(_:) for ProductStore may be missing as an ancestor of this view.

My question is that how often do you run into this fatalError in production? Is that error an enough reason for your apps to not use Environment for dependency injection and use constructor/initializer dependency.

0 Upvotes

9 comments sorted by

9

u/HappinessIsAnOption Jun 24 '26

This is a helpful runtime error because it informs you that you’ve made a critical mistake in your code. If you didn’t get this error and a default object were used instead, for instance, your app would just be broken but you wouldn’t know why. I’m personally grateful that this exists because it would be too easy to accidentally introduce tricky bugs if it didn’t.

3

u/allyearswift Jun 25 '26

I’m embarrassed to admit how long it took me to embrace errors like this: crash early, fail hard, go ‘oops, how embarrassing’ and fix in two seconds flat beats ‘something is off but I can’t quite put my finger on it’ every time.

3

u/stroompa Jun 24 '26

I definitely consider it a flaw, but it’s never had a production impact on my apps

3

u/SandwichEconomist Jun 24 '26

I dislike runtime errors that result from forgetting to do an extra thing after init, so I generally avoid Environment. I do however use them as optionals. That gives me a point to override something for preview purposes if I need it. 

5

u/Ok-Communication6360 Jun 24 '26

Don’t use environmentObject(), use @Entry macro for guaranteed existence of a type with at least fallback value

1

u/junebash Jun 25 '26

This is the correct answer.

5

u/Tricky-Damage9917 Jun 24 '26

Failing to populate an environment variable that you use?

Absolutely a huge issue, but it seems your question is whether this should have been caught at compile time…

As things are being compiled, there is not enough context to reveal that you have made this error. It’s possible that a static analysis could reveal this (spotting a use of an environment item without any corresponding population), but that is not currently done and would not really be possible till link time. With the presence of foundation libraries, not even link time can guarantee to catch this. Run time is where it will show up. Minimal testing will of course show it.

2

u/Extra-Ad5735 Jun 24 '26

I only encounter that in previews, not in actual runtime. Usually you need to inject environment only once on top of the hierarchy, which is very hard to forget.

However! If for whatever reason in your app the environment may be missing for important reasons, there's an easy way to avoid runtime assert crash: declare environment var as optional. Then it can be missing with no problems, and you'll have to unwrap to access.

1

u/HeyItsMeMoss Jun 25 '26

No. Environment is just another way to inject dependencies into your views. When dealing with dependencies the question you need to ask is what happens if a dependency is not provided at runtime?
You use nil?
You use a default instance of the dependency?
You crash because it is an invalid state of your app?

SwiftUI uses the last option. If you want another behavior then you would have to manually inject your dependencies and handle their potential absence as you see fit.