Issue #605
I use custom TextView
in a master detail application.
import SwiftUI
struct TextView: NSViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: Context) -> NSTextView {
let textView = NSTextView()
textView.delegate = context.coordinator
return textView
}
func updateNSView(_ nsView: NSTextView, context: Context) {
guard nsView.string != text else { return }
nsView.string = text
}
class Coordinator: NSObject, NSTextViewDelegate {
let parent: TextView
init(_ textView: TextView) {
self.parent = textView
}
func textDidChange(_ notification: Notification) {
guard let textView = notification.object as? NSTextView else { return }
self.parent.text = textView.string
}
}
}
No matter which item user selects, textView always updates the first one
struct Book {
var name: String = ""
}
class Store: ObservableObject {
@Published var books: [Book] = []
}
struct MainView: View {
@EnvironmentObject var store: Store
var body: some View {
List {
ForEach(store.books.enumerated().map({ $0 }), id: \.element.id) { index, book in {
Text(book.name)
.onTapGesture {
self.store.selectedIndex = index
}
}
}
HStack {
TextView($store.books[store.selectedIndex].name)
}
}
}
The fix is to pass selected object instead of using subscript
struct MainView: View {
@EnvironmentObject var store: Store
var body: some View {
List {
ForEach(store.books.enumerated().map({ $0 }), id: \.element.id) { index, book in {
Text(book.name)
.onTapGesture {
self.store.selectedBook = self.store.books[index]
}
}
}
HStack {
TextView($store.selectedBook.name)
}
}
}
And we need to save selectedBook
class Store: ObservableObject {
@Published var books: [Book] = []
@Published var selectedBook: Book = Book(name: "") {
didSet {
saveSelected()
}
}
func saveSelected() {
guard let index = self.books.firstIndex(where: { $0.id == selectedBook.id }) else {
return
}
books[index] = selectedBook
}
}
Read more
Updated at 2020-06-01 02:13:51