SOLVED, thanks to @JoakimDanielson. Hope this helps others...
I was trying to understand @State and @Binding, and was getting stuck in the preview for SwiftUI.
As you will see, I was trying to learn how to store the model outside of the view, and give controls (e.g., the "up!!" button) the power to update the model.
The app:
import SwiftUI
@main
struct BinnderApp: App {
@State private var appModel: Model = Model(value: 42)
var body: some Scene {
WindowGroup {
ContentView(myModel: $appModel)
}
}
}
struct Model {
var value: Int
mutating func increment() {
value += 1
}
}
The view:
import SwiftUI
struct ContentView: View {
@Binding var myModel: Model
var body: some View {
VStack {
Button("up!!") {
myModel.increment()
}
Text("the value is \(myModel.value)")
}
}
}
#Preview {
// @Binding var myModel: Model = Model(value: 0). //. this was the problem
@Previewable @State var myModel: Model = Model(value: 0) // solution!
ContentView(myModel: $myModel)
}
In the [original] first line of #Preview, I got this error: Cannot convert value of type 'Model' to specified type 'Binding<Model>'
Of course I tried different combinations of things to squash the error, no joy.
Joakim gave me the solution: use @Previewable @State, which I never would have seen.
Let's take a moment to see why @State makes sense.
Use @State to specify the original source location of some data that you plan to use in a different scope.
Use @Binding in that destination (usually a View) to declare that data. Using @Binding gives the View read-write access to the data.
So in the App above, I declare the appModel property as a @State variable; then I pass it to the ContentView using the dollar sign to indicate that it is a binding. In the View, it's a property (myModel) declared as a @Binding.
The problem for me came in setting up the Preview. The key to the solution (besides @Previewable, still a bit of a mystery to me) is that even though the Preview is coded in the "View" file, it still calls ContentView() just like in the "App" file. So the Model that gets passed in has to be declared @Source (and initialized) in that "Preview" section.
@Bindingwith@Previewable @State. You want a State and not Binding property wrapper to start with an with the new Preview macro you can use Previable to declare such property@Statetells us that this is the ultimate source of the data, as it is in the "app" file. Here, in this#Previewthing, that code—which callsContentView()—substitutes for the app for the purposes of creating that view. Right?