There are other answers on SO about this issue but none seen to solve the problem because in my case I am using a NSViewRepresentable cocoa view, that is not exactly a SwiftUI view.
I have this code:
struct MyObject: Hashable, Identifiable {
let id: UUID = UUID()
var name, brand: String
init(name: String = "", brand: String = "") {
self.name = varName
self.brand = brand
}
}
final class Model:ObservableObject {
@Published var objects = (0..<3).compactMap {_ in
return MyObject()
}
}
struct ContentView: View {
private let columns = [GridItem(.flexible()), GridItem(.flexible())]
@StateObject private var model = Model()
var body: some View {
VStack{
LazyVGrid(
columns: columns,
alignment: .center,
spacing: 10,
pinnedViews: []
) {
ForEach($model.objects, id:\.id) {$object in
MyTextField($initObject)
}
}
}
.padding(20)
}
}
struct MyTextField: View {
@Binding private var initObject:InitObject
init(_ initObject:Binding<InitObject>) {
_initObject = initObject
}
var body: some View {
AppKitTextField(property: $initObject.name,
placeholder: "name",
fontName:"Avenir-Medium",
fontSize:18) { text in
}
MyAppKitTextField(property: $initObject.type,
placeholder: "type",
fontName:"Avenir-Medium",
fontSize:18)
}
}
The problem is that MyAppKitTextField is a AppKit NSTextField NSViewRepresentable, like this:
public struct AppKitTextField: NSViewRepresentable {
public typealias NSViewType = NSTextField
@Binding var property: String
public init(property: Binding<String>) {
self._property = property
}
public class Coordinator: NSObject, NSTextFieldDelegate {
@Binding private var text: String
init(text: Binding<String>) {
self._text = text
}
}
public func makeNSView(context: NSViewRepresentableContext<AppKitTextField>) -> NSTextField {
let textField = NSTextField()
textField.delegate = context.coordinator
textField.stringValue = property
return textField
}
public func makeCoordinator() -> AppKitTextField.Coordinator {
return Coordinator(text: $property)
}
public func updateNSView(_ nsView: NSTextField, context: Context) {
nsView.stringValue = property
}
}
}
My problem is the line
@Binding var property: String
When I try to use this view I see this error:
Accessing StateObject's object without being installed on a View. This will create a new instance each time.
My first guess is
@Bindingproperty wrapper shouldn't be used in theCoordinatorclass since it's not aViewwhere@Bindingis designed to be used. Instead, you can either useBinding<String>or just a closure since you only need to set anyway.My second guess is this mistake:
It should be:
FYI Binding is just a pair of get/set closures, there is no need to give the Binding to the Coordinator because it doesn't need the get, thats the reason for the set only
textDidChangeclosure which you should invoke from your delegate or action handler.