Как использовать BindableObjects (EnviromentObject)?

Я использую новый SwiftUI. У меня есть класс UserUpdate, который является классом Bindable Object, и я хочу изменить эти переменные и автоматически обновить пользовательский интерфейс.

Я успешно обновляю эти значения, но представления в моей структуре пользовательского интерфейса не обновляются, когда я изменяю переменную в классе UserUpdate.

Только изменяется, когда я изменяю переменную @EnviromentObject в самой структуре пользовательского интерфейса.

Это мой класс Bindable Object:

final class UserUpdate: BindableObject {
    let didChange = PassthroughSubject<Any, Never>()

    var allUsers: [User] = [] {
        didSet {
            print(allUsers)
            didChange.send(allUsers)
        }
    }

    var firstName: String = "" {
        didSet {
            didChange.send(firstName)
        }
    }

    var lastName: String = "" {
        didSet {
            didChange.send(lastName)
        }
    }
}

Это мой пользовательский класс:

struct User: Identifiable {
    let id: Int
    let firstName, lastName: String
}

Вот как я настраиваю свой пользовательский интерфейс:

struct ContentView : View {
    @EnvironmentObject var bindableUser: UserUpdate

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                Text("All Users:").bold().padding(.leading, 10)
                List {
                    ForEach(bindableUser.allUsers) { user in
                        Text("\(user.firstName) \(user.lastName)")
                    }
                }
            }
        }
    }
}

Здесь я изменяю переменные в UserUpdate:

class TestBind {
    static let instance = TestBind()

    let userUpdate = UserUpdate()

    func bind() {
        let user = User(id: userUpdate.allUsers.count, firstName: "Heyy", lastName: "worked")
        userUpdate.allUsers.append(user)
    }
}

Это потому, что ваша переменная представления (bindableUser) привязана к потоку EnvirnomentObject. Представление не узнает, обновите ли вы какой-либо другой поток.

Sada 07.06.2019 21:58

И как я могу это решить? Я не понимаю, почему Bindable Object полезен тогда.

SwiftiSwift 07.06.2019 22:04

Вы привязали свою среду к представлению в делегате сцены? См. stackoverflow.com/questions/56476007/…

Paulw11 07.06.2019 23:14

@ Paulw11 Я уже это сделал

SwiftiSwift 08.06.2019 06:09

Протокол BindableObject теперь переименован в ObservableObject, ObjectBinding теперь ObservedObject и didChange теперь objectWillChange.

Stoyan 06.11.2019 13:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
2 658
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я узнал, что мне пришлось вызвать метод из моего пользовательского интерфейса, чтобы заставить его работать, чтобы он работал в том же потоке.

Например по этому:

struct ContentView : View {
@EnvironmentObject var networkManager: NetworkManager

var body: some View {
    VStack {
        Button(action: {
            self.networkManager.getAllCourses()
        }, label: {
            Text("Get All Courses")
        })

        List(networkManager.courses.identified(by: \.name)) {
            Text($0.name)
        }
    }
}
}

Если я не ошибаюсь, вы должны внедрить экземпляр UserUpdate в свой ContentView, возможно, в SceneDelegate, используя ContentView().environmentObject(UserUpdate()).

В этом случае у вас есть 2 разных экземпляра класса UserUpdate, первый создан в классе SceneDelegate, а второй создан в классе TestBind.

Проблема в том, что у вас есть один экземпляр, привязанный к представлению (и вызывающий перезагрузку представления при обновлении), и тот, который вы фактически изменяете (в классе TestBind), который совершенно не связан с представлением.

Вы должны найти способ использовать тот же экземпляр в представлении и в классе TestBind (например, используя ContentView().environmentObject(TestBind.instance.userUpdate)

Другие вопросы по теме