Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a value from an EnvironmentObject to a class instance in SwiftUI?

I'm trying to assign the value from an EnvironmentObject called userSettings to a class instance called categoryData, I get an error when trying to assign the value to the class here ObserverCategory(userID: self.userSettings.id)

Error says: Cannot use instance member 'userSettings' within property initializer; property initializers run before 'self' is available

Here's my code:

This is my class for the environment object:

//user settings
final class UserSettings: ObservableObject {
    @Published var name : String = String()
    @Published var id : String = "12345"
}

And next is the code where I'm trying to assign its values:

//user settings
@EnvironmentObject var userSettings: UserSettings

//instance of observer object
@ObservedObject var categoryData = ObserverCategory(userID: userSettings.id)

class ObserverCategory : ObservableObject {

    let userID : String

    init(userID: String) {

        let db = Firestore.firestore().collection("users/\(userID)/categories") //

        db.addSnapshotListener { (snap, err) in
            if err != nil {
                print((err?.localizedDescription)!)
                return
            }

            for doc in snap!.documentChanges {

                //code 

            }
        }
    }
}

Can somebody guide me to solve this error?

Thanks

like image 327
Lorenzo R Avatar asked Nov 23 '19 16:11

Lorenzo R


People also ask

When should you assign a value to an @EnvironmentObject property?

Just like @ObservedObject , you never assign a value to an @EnvironmentObject property. Instead, it should be passed in from elsewhere, and ultimately you're probably going to want to use @StateObject to create it somewhere. However, unlike @ObservedObject we don't pass our objects into other views by hand.

What does @environment do SwiftUI?

You can use the @EnvironmentObject Property Wrapper in SwiftUI to provide environment values to child views without injecting them manually.

What is the difference between an @environment property and an @EnvironmentObject property?

SwiftUI gives us both @Environment and @EnvironmentObject property wrappers, but they are subtly different: whereas @EnvironmentObject allows us to inject arbitrary values into the environment, @Environment is specifically there to work with SwiftUI's own pre-defined keys.


1 Answers

Because the @EnvironmentObject and @ObservedObject are initializing at the same time. So you cant use one of them as an argument for another one.

You can make the ObservedObject more lazy. So you can associate it the EnvironmentObject when it's available. for example:

struct CategoryView: View {

    //instance of observer object
    @ObservedObject var categoryData: ObserverCategory

    var body: some View { ,,, }
}

Then pass it like:

struct ContentView: View {

    //user settings
    @EnvironmentObject var userSettings: UserSettings

    var body: some View {
        CategoryView(categoryData: ObserverCategory(userID: userSettings.id))
    }
}
like image 162
Mojtaba Hosseini Avatar answered Oct 25 '22 09:10

Mojtaba Hosseini