Я использую новый 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)
}
}
И как я могу это решить? Я не понимаю, почему Bindable Object полезен тогда.
Вы привязали свою среду к представлению в делегате сцены? См. stackoverflow.com/questions/56476007/…
@ Paulw11 Я уже это сделал
Протокол BindableObject теперь переименован в ObservableObject, ObjectBinding теперь ObservedObject и didChange теперь objectWillChange.





Я узнал, что мне пришлось вызвать метод из моего пользовательского интерфейса, чтобы заставить его работать, чтобы он работал в том же потоке.
Например по этому:
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)
Это потому, что ваша переменная представления (bindableUser) привязана к потоку EnvirnomentObject. Представление не узнает, обновите ли вы какой-либо другой поток.