Issue #605
I use custom TextView
in a master detail application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import SwiftUIstruct 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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