Изменение на @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.

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