How does a SwiftUI View with a non-nil property decorated with @EnvironmentObject get around that property not being set during initialization? I know .environmentObject() does set the value but the Swift rules as I understand them would not allow that. I encountered this with the userData property of LandmarkList from the SwiftUI Tutorial:
https://developer.apple.com/tutorials/swiftui
On Twitter I was told: "Think of it as an implicitly unwrapped optional. It’s just initialized to nil until the value is available."
I agree this is the behavior I'm observing but I don't understand how the language rules are being manipulated to accomplish this. Normally a non nil property would have to be passed in through the initializer.
In my testings going through the Landmark tutorial, when I removed the call to .environmentObject() below I was surprised I did not get a compiler warning but instead a runtime error which feels very unSwift-like.
Thanks for any help or pointers.
https://developer.apple.com/tutorials/swiftui
On Twitter I was told: "Think of it as an implicitly unwrapped optional. It’s just initialized to nil until the value is available."
I agree this is the behavior I'm observing but I don't understand how the language rules are being manipulated to accomplish this. Normally a non nil property would have to be passed in through the initializer.
In my testings going through the Landmark tutorial, when I removed the call to .environmentObject() below I was surprised I did not get a compiler warning but instead a runtime error which feels very unSwift-like.
Code Block window.rootViewController = UIHostingController( rootView: LandmarkList() .environmentObject(UserData()) )
Thanks for any help or pointers.
To understand the behavior of @EnvironmentObject in detail, you need to know how property wrappers work in Swift.
SE-0258Property Wrappers
If you declare a property with @EnvironmentObject like this:
it is translated by the Swift compiler and generates some code equivalent to the following:
So, the property userData actually is a computed property which does not need initialization.
And implicitly declared stored property is implicitly initialized with the right wrapping struct.
Swift rules applies to these translated properties, the language rules are not manipulated.
SE-0258Property Wrappers
If you declare a property with @EnvironmentObject like this:
Code Block @EnvironmentObject var userData: UserData
it is translated by the Swift compiler and generates some code equivalent to the following:
Code Block var _userData: EnvironmentObject<UserData> = EnvironmentObject<UserData>() var userData: UserData { get {_userData.wrappedValue} }
So, the property userData actually is a computed property which does not need initialization.
And implicitly declared stored property is implicitly initialized with the right wrapping struct.
Swift rules applies to these translated properties, the language rules are not manipulated.