Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Assign `@Environment` value to `Binding` parameter

I’m creating a MacOS app and wanted to store the app state in memory and pass it around to a few components, but also update the state from those components.

import SwiftUI

@Observable
class Book {
  var title: String
  
  init(_ title: String) {
    self.title = title
  }
}

struct ParentView : View {
  @State private var myBook = Book("First title")
  
  var body: some View {
    VStack {
      Text("Book title (Parent): \(myBook.title)")
      
      ChildView()
        .frame(width: 200, height: 100)
        .background(.teal)
        .environment(myBook) // Add myBook to environment
    }
  }
}

struct ChildView : View {
  @Environment(Book.self) var myBook: Book
    
  var body: some View {
    VStack {
      Text("Book title (Child): \(myBook.title)")
      
      TextField("Book title", text: myBook.title) // Error here!!!
    }
  }
}

This throws an error when I attempt to pass myBook.title as a Binding to the TextField.

Cannot convert value of type 'String' to expected argument type 'Binding<String>'

enter image description here

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This makes sense but normally, but since the Book is an @Observable class I can update the values and have the updates reflected across all usages.

What’s the best way to assign an @Observable @Environment class property to a Binding parameter?

>Solution :

To make it a Binding, you need to use Bindable:

struct ChildView : View {
  @Environment(Book.self) var myBook: Book
    
  var body: some View {
    VStack {
      Text("Book title (Child): \(myBook.title)")
      
      @Bindable var myBook = myBook
      TextField("Book title", text: $myBook.title)
    }
  }
}

Documentation (which includes a similar example): https://developer.apple.com/documentation/swiftui/bindable

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading