How to use Swift Macros with @Observable and @Environment?

1.3k Views Asked by At

I'm trying to use the new Swift Macros using @Observable and @Environment with the following code:

import SwiftUI
import Observation

@Observable class Note {
    var text = ""
}

struct ContentView: View {
    @State var note = Note()
    
    var body: some View {
        FormView()
            .environment(note)
    }
}

struct FormView: View {
    @Environment(Note.self) var note
    
    var body: some View {
        Form {
            TextField("write here", text: $note.text)
        }
    }
}

However, it's unable to build with the following error:

Cannot find '$note' in scope

Removing the $ in $note results in:

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

1

There are 1 best solutions below

2
On BEST ANSWER

Currently (as of iOS 17/macOS 15 beta 2) objects received via an @Environment object aren’t directly bindable.

The workaround (as suggested by an Apple engineer in one of the WWDC slack rooms) is to redeclare a bindable local reference in your body:

struct FormView: View {
    @Environment(Note.self) var note
    
    var body: some View {
        @Bindable var note = note // add this line
        Form {
            TextField("write here", text: $note.text)
        }
    }
}

If you are frustrated with this, do file a feedback report with Apple – the more feedback we give them about elements like this, the higher priority a fix is likely to become.