SwiftUI ObservedObject не обновляет представление после успешного входа в систему

Чтобы показать мой контент из моего корневого представления после успешного входа в систему, я попытался с ObservedObject, и с EnvironmentObject, но безрезультатно.

Например, следующим образом:

struct RootView: View {

    @EnvironmentObject var loginManager: LoginManager

    var body: some View {
        Group {
            if loginManager.isLoggedIn {
                SegmentedView()
            }
            else {
                WelcomeView()
            }
        }
    }
}

class LoginManager: ObservableObject {
    
    static let shared = LoginManager()
    var cancellable = Set<AnyCancellable>()
    @Published var isLoggedIn = false

    ...
    
    func login(...) {
        ...
        // on success
        self.isLoggedIn = true
    }

В LoginManager сохраняется в SceneDelegate и поместите в среду:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    var loginManager = LoginManager.shared
    ...

    // the view passed to window.rootUiewController via UIHostingController
    let contentView = RootView().environmentObject(loginManager)

После входа он снова возвращается в мою WelcomeView. Что мне не хватает?

РЕДАКТИРОВАТЬ

Вот новый аспект. У меня есть модель просмотра дляLoginViewдля управления данными в полях даты. Когда нажимается кнопка входа в систему, я вызываюlogin() в этой модели представления.

Мне нужно два .sink обратные вызовы в модели представления, потому что я должен отклонить индикатор загрузки, установив loading значение false.

Поэтому я не могу позвонить self.isLoggedIn = true прямо потому, что я нахожусь в модели представления, а не LoginManager. Вместо этого я звоню

self.loginManager.isLoggedIn = true 

и я подозреваю, что эта линия не работает.

Связь между моделью представления и менеджером входа выполняется следующим образом

@ObservedObject var loginManager = LoginManager.shared

Однако после переноса этого на LoginManager, Я действительно звоню self.isLoggedInоттуда. Это все еще не работает.

У меня два тезиса:

  1. Возможно, представление неправильно настроено с Group и т.д. Я тоже пробовал использовать @ViewBuilder и т.д, без разницы.

  2. Возможно, есть два экземпляра LoginManager, или RootView каким-то образом получить повторную инициализацию с новым экземпляром, где isLoggedInложно. Но я создавал такие синглтоны Swift целую вечность:

    static let shared = LoginManager()

и никогда не было проблем.

Как упоминалось в комментариях, есть еще одна ошибка, с которой я столкнулся при переключении всех на @EnvironmentObject:

Fatal error: No ObservableObject of type LoginManager found. A View.environmentObject(_:) for LoginManager may be missing as an ancestor of this view.: file SwiftUI, line 0

1 ответ

Решение

Думаю, у меня ошибка.

Я предположил .sink(receiveCompletion: всегда есть ошибка из-за шаблона, о котором я имел в виду. Но вызывается блок завершения несмотря ни на что.

К сожалению, если вы вставите параметр error in этого никогда не будет nil но содержать что-то вроде

Combine.Subscribers.Completion<module.CustomError>.finished

Так что, я думаю, вам не следует снова проверять наличие ошибок.

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