BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Initialization Issue

Forums > SwiftUI

@ASH  

I have some lengthy code with explicit colors, that works . I have reduced the cogent parts to the simplification below . My View Model is passed to my view as an environment object.

struct ConteView: View {

@EnvironmentObject var game: colorGameVM ... // a bunch of @State vars ...

@State var angGrad: [Color] = [Color.red,Color.white,Color.blue]

var body: some View { // bunch of stuff }

}

I want to dynamically use colors from my View Model, so I changed it like this

struct ConteView: View {

@EnvironmentObject var game: colorGameVM ... // a bunch of @State vars ...

@State var angGrad: [Color] = [game.color1,game.color2,game.color3]

var body: some View { // bunch of stuff }

}

and got the "Cannot use instance member 'game' within property initializer; property initializers run before 'self' is available" error on the angGrad line.

I left the @State type def and moved angGrad code into an initializer but get an error "Variable 'self.manager' used before being initialized" in the init. I don't understand what this means. I cannot bring the game var into the init because as an Environment Object it's a get only property.

struct ConteView: View {

@EnvironmentObject var game: colorGameVM ... // a bunch of @State vars ...

@State var angGrad: [Color]

init() { self.angGrad = [game.color1,game.color2,game.color3] }

var body: some View { // bunch of stuff }

}

Any suggestions on how to achieve this? BTW, I know I can access the game.color directly in my View, the angGrad is a an array used for a background color gradient.

   

The explanation why you can't use an EnvironmentObject in init is explained by roosterboy here.

Because when init is called on a View, that's no guarantee it will actually be displayed on screen. (e.g., the destination of a NavigationLink gets its init called when the NavigationLink is rendered, even if the user never follows the link) It's not until the body is rendered that it will be displayed and so that's when an environment needs to exist. If you used an environment object or value at init time, it could be different by the time the View is actually rendered.

Please, use code tags next time you describe your problem because it's easier to understand what's your code.

One solution could be that your ViewModel is passed in the init and it's not a StateObject but a ObserverdObject.

   

@ASH  

Thank you @Hatsushira for that explanation. I will probably just rework the code to access the game.color values directly.

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.