Reputation: 465
I have a ForEach
binding to an array of items. Each item has an index (which represents how it should be sorted), and some text. Each row in the ForEach
has an NSTextView
in an NSViewRepresentable
(I can't use TextEditor
for various reasons), which uses the binding for the item's text
. However, after sorting the list, if I update the NSTextView, one of the other views gets the update as well:
Here's my code:
struct ListItem: Hashable, Identifiable {
var index: Int
var text: String
var id = UUID()
static let initialItems: [ListItem] = [
.init(index: 2, text: "String 2"),
.init(index: 0, text: "String 0"),
.init(index: 1, text: "String 1"),
]
}
struct ContentView: View {
@State var items = ListItem.initialItems
var body: some View {
Form {
ForEach($items) { item in
HStack {
TextField("Index: ", value: item.index, format: .number)
.textFieldStyle(.roundedBorder)
TVRep(text: item.text)
}
}
Button("Sort!") {
items.sort(by: {$0.index < $1.index})
}
}
.padding()
}
}
struct TVRep: NSViewRepresentable {
@Binding var text: String
func makeNSView(context: Context) -> NSTextView {
let view = NSTextView()
view.string = text
view.delegate = context.coordinator
return view
}
func updateNSView(_ nsView: NSTextView, context: Context) {
nsView.string = text
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, NSTextViewDelegate {
var parent: TVRep!
init(parent: TVRep) {
super.init()
self.parent = parent
}
func textDidChange(_ notification: Notification) {
guard let tv = notification.object as? NSTextView else {return}
parent.text = tv.string
}
}
}
This doesn't occur when using SwiftUI's built-in TextEditor
. Interestingly, this only seems to happen when I update the text
binding's value within the Representable view - if I don't have the delegate method updating the binding value, this doesn't occur.
I do know that if I call sorted(by:)
in the ForEach
argument that it will update properly, but that means that the moment that the TextField
for the index is updated, the views are sorted, while I want to be able to sort them manually.
Upvotes: 0
Views: 176