Search code examples
iosswiftswiftuiobservable

How to make observable class variable @Bindable when it is also used as @Environment?


I have following global observable for a user profile:

@Observable class User {
  var username = ""
  var isAdmin = false
}

This observable is then set as an environment and accessed from various places like so

@Environment(User.self) private var user

I'm now trying to figure out how I can use @Bindable here in order to have a textfield that could update username, but simply using $ doesn't seem to work i.e.

TextField(text: $user.username)

Above throws an error like this Cannot find '$user' in scope


Solution

  • @Bindable can be used with local variables:

    In body, just do

    @Bindable var bindableUser = user
    

    to make a Bindable user. Then you can use $bindableUser.someProperty as usual.

    Here is a simple example:

    struct Foo: View {
        @Environment(User.self) var user
        
        var body: some View {
            Text(user.username)
            Text(user.isAdmin ? "Yes" : "No")
            @Bindable var bindableUser = user
            TextField("Foo", text: $bindableUser.username)
            Toggle("Foo", isOn: $bindableUser.isAdmin)
        }
    }