Binding with ForEach or List doesn't work anymore when using @Observable macro

Hi. The binding in a ForEach or List view doesn't work anymore when using the @Observable macro to create the observable object. For example, the following are the modifications I introduced to the Apple's example called "Migrating from the Observable Object Protocol to the Observable Macro" https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro


struct LibraryView: View {
    @Environment(Library.self) private var library
    
    var body: some View {
        List($library.books) { $book in
            BookView(book: book)
        }
    }
}

All I did was to add the $ to turn the reference to library.books into a binding but I got the error "Cannot find '$library' in scope"

Is this a bug or the procedure to use binding in lists changed?

Thanks

Replies

To get bindings from an Observable class, you need to use the @Bindable property wrapper as normal. However, the bindable value is coming from the environment so this is different.

Whether this solution is a workaround or the intention going forward, it works nonetheless.

var body: some View {
    @Bindable var library = library // place in view body

    List($library.books) { $book in
        BookView(book: book)
    }
}
  • Oh, wow. That's a weird workaround. Thanks.

  • This solution was actually recommended by an Apple engineer during one of the WWDC activities. To add a binding to the @Environment property wrapper would mean adding a projectedValue. If that was something people would like to see (which it is) then they suggested filing a feedback report.

Add a Comment

At the moment, @Environment can't use for Binding

I don't know whether it's a bug or not

https://developer.apple.com/forums/thread/732658