Объект SwiftUI ObservedObject каждый раз инициируется заново

#ios #swift #swiftui #uiviewrepresentable #environmentobject

Вопрос:

У меня есть простой класс для хранения некоторых данных в моем приложении SwiftUI:

 final class UserData: ObservableObject  {
    @Published var id = 1
    @Published var name = "Name"
    @Published var description = "Initial text"
}
 

Я также определил его как EnvironmentObject в основной структуре приложения:

 ContentView(document: file.$document)
    .environmentObject(UserData())
 

В моем представлении содержимого я встроил текстовое представление UIKit:

 EditorTextView(document: $document.text)
 

Где EditorTextView UITextView -это то, что применяется через UIViewRepresentable .

Теперь я пытаюсь обновить данные пользователя в EditorTextView, например, сохранить некоторые пользовательские данные UserData.description . Поэтому я определил класс внутри своего координатора следующим образом (код просто для примера):

 class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData = UserData()
    ...
    // Somewhere in the code, I update UserData when user taps Enter:
    func textViewDidChange(_ textView: UITextView) {
        if (textView.text.last == "n") {
            userData.description = "My New Text"
        }
    }
 

Моя проблема в том, что:

Хотя он обновляется с помощью «Мой новый текст» (как показывает отладчик), значение userData.description снова инициируется со значением «Начальный текст». Это похоже на то, как если бы класс UserData создавался каждый раз.

Я пытался использовать @StateObject вместо @ObservedObject, но это не имеет значения.

Комментарии:

1. Вы должны решить, является ли это объектом окружающей среды или наблюдаемым объектом?

2. Это объект среды (чтобы сделать его доступным для всех представлений), но я использовал @ObservedObject его в оболочке uikit, потому что я не мог @EnvironmentObject там использовать

Ответ №1:

«Это похоже на то, как если бы класс UserData создавался каждый раз».

Он создается каждый раз, прямо здесь:

 class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData = UserData()  // <--- here
 

Попробуйте вместо этого и передайте данные пользователя извне:

 class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData: UserData
 

Как правило, вы также делаете это в своей основной структуре приложения:

 @StateObject var userData = UserData()
...
ContentView(document: file.$document).environmentObject(userData)
 

Комментарии:

1.Спасибо, но как инициализировать данные пользователя в функции инициализации координатора? init(_ parent: EditorTextView) { self.parent = parent }

2. У вас есть «@ObservedObject var userData: данные пользователя» в родительском файле. Затем в координаторе у вас есть инициализация с родителем, затем вы можете ссылаться на нее в координаторе, например: «self.parent.userData».

3. Поэтому я перешел @ObservedObject var userData: UserData от координатора к родителю, который является EditorTextView, но начинают появляться ошибки. Я создал Минимальный воспроизводимый пример, пожалуйста, посмотрите здесь

4. Я не могу загрузить ваш код с этого сайта. Из моего краткого взгляда на это: мне ясно, что вам нужно прочитать о ObservedObject и EnvironmentObject, как их использовать и передавать из одного представления в другое. Простое руководство по использованию находится по адресу: hackingwithswift.com/quick-start/swiftui/… В вашем представлении контента у вас даже нет: «@EnvironmentObject var userData: Данные пользователя». Мой совет: изучите немного больше о ObservedObject и EnvironmentObject.