Изменение на @Published var в @EnvironmentObject не отражается сразу
В этом конкретном случае, когда я пытаюсь изменить @EnvironmentObject
"s @Published var
Я считаю, что представление не является недействительным и обновляется немедленно. Вместо этого изменение в переменной отражается только после перехода от модального режима и возврата назад.
import SwiftUI
final class UserData: NSObject, ObservableObject {
@Published var changeView: Bool = false
}
struct MasterView: View {
@EnvironmentObject var userData: UserData
@State var showModal: Bool = false
var body: some View {
Button(action: { self.showModal.toggle() }) {
Text("Open Modal")
}.sheet(isPresented: $showModal, content: {
Modal(showModal: self.$showModal)
.environmentObject(self.userData)
} )
}
}
struct Modal: View {
@EnvironmentObject var userData: UserData
@Binding var showModal: Bool
var body: some View {
VStack {
if userData.changeView {
Text("The view has changed")
} else {
Button(action: { self.userData.changeView.toggle() }) {
Text("Change View")
}
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MasterView().environmentObject(UserData())
}
}
#endif
Это ошибка или я что-то не так делаю?
Это работает, если changeView
это @State var
внутри модал. Это также работает, если это @State var
внутри MasterView
с @Binding var
внутри Modal
, Это просто не работает с этой настройкой.
2 ответа
Изменения
final class UserData: NSObject, ObservableObject {
в
final class UserData: ObservableObject {
действительно решает проблему в Xcode11 Beta6. SwiftUI, кажется, не справляется NSObject
реализация подклассов ObservableObject
правильно (по крайней мере, это не называет это внутренним willSet
блоки вроде).
Пара вещей.
- Ваша настройка не работает, если вы переместите кнопку в
MasterView
или. - У вас нет
import Combine
в вашем коде (не волнуйтесь, это само по себе не помогает).
Вот исправление. Я не знаю, является ли это ошибкой или просто плохой документацией - IIRC утверждает, что objectWillChange
неявно.
Вместе с добавлением import Combine
в свой код, измените свой UserData
к этому:
final class UserData: NSObject, ObservableObject {
var objectWillChange = PassthroughSubject<Void, Never>()
@Published var changeView: Bool = false {
willSet {
objectWillChange.send()
}
}
}
Я проверял вещи, и это работает.
В Xcode 11 GM2, если вы переопределили objectWillChange
, тогда ему нужно позвонить send()
по установщику опубликованной переменной.
Если вы не отменяете objectWillChange
, после изменения опубликованных переменных в @EnvironmentObject или @ObservedObject представление должно быть обновлено. Поскольку в Xcode 11 GM2objectWillChange
уже есть экземпляр по умолчанию, больше нет необходимости указывать его в ObservableObject
.