Как перезагрузить UIViewRepresentable в основных видах деталей - PullRequest
0 голосов
/ 14 февраля 2020

В приложении основных деталей у меня есть список элементов и подробный вид для каждого элемента. В подробном представлении есть 1 пользовательский ввод текста, поэтому я использую UIViewRepresentable

struct TextView: UIViewRepresentable {
    @Binding var text: String

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextView {
        let myTextView = UITextView()
        myTextView.delegate = context.coordinator
        return myTextView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
    }

    class Coordinator : NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ uiTextView: TextView) {
            self.parent = uiTextView
        }

        func textViewDidChange(_ textView: UITextView) {
            self.parent.text = textView.text
        }
    }
}

Когда пользователь выбирает элемент из списка, мы показываем подробный вид для этого элемента. Все отлично работает при отображении данных. Однако после установки точек останова я вижу, что пользовательский TextView создается ровно 1 раз, поэтому myTextView.delegate = context.coordinator устанавливается только для первого элемента

Так что, когда пользователь выбирает другой элемент и редактирует ввод текста в в подробном представлении всегда обновляется первый элемент в списке.

Вот как используется TextView

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)
        }
    }
}

Я попытался установить UITextViewDelegate в updateUIView, но та же проблема. Как мы можем заставить SwiftUI обновить этот пользовательский TextView так, чтобы UITextViewDelegate был установлен для каждого координатора?

P / S 1: Если я использую обычный TextField, тогда он работает. Обновляется текст для выбранной книги

P / S 2: Если я передам напрямую $store.selectedBook.name вместо использования нижнего индекса $store.books[store.selectedIndex].name, то он тоже будет работать

...