Обработка ошибки Firebase Auth в приложении SwiftUI Combine - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть приложение, в котором пользователи могут зарегистрироваться и войти в систему, используя Firebase. Однако я не могу предупредить пользователя о любых ошибках в представлении.

Сначала у нас есть UserStore , который является ObservableObject и инициализируется как EnvironmentObject при настройке. вверх вид в SceneDelegate.

let appView = AppView().environmentObject(userStore)

  if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: appView)
        self.window = window
        window.makeKeyAndVisible()

}

Затем мы регистрируемся или авторизируемся в View следующим образом.

В представлении

self.userStore.logIn(email: self.email, password: self.password)
self.isLoggingIn = true

if self.userStore.failedToLogin {
   self.isLoggingIn = false
   self.alertTitle = "There seems to be a problem"
   self.alertBody = self.userStore.errorMessage
   self.showingAlert = true
}

Тогда фактический метод должен обновить значения свойств UserStore, которые затем обновят представление и отобразят предупреждение, однако это не так ,

Вход

// Session Properties
@Published var isLoggedIn = false {didSet{didChange.send() }}
@Published var isNewUser = false {didSet{didChange.send() }}
@Published var failedToCreateAccount = false {didSet{didChange.send() }}
@Published var failedToLogin = false {didSet{didChange.send() }}
@Published var errorMessage = "" {didSet{didChange.send() }}

init () {
  handle = Auth.auth().addStateDidChangeListener { (auth, user) in
    if let user = user {
      self.session = user
      self.isLoggedIn = true
      //Change isNewUser is user document exists?
   } else {
      self.session = nil
      self.isLoggedIn = false
    }
  }
}

func logIn(email: String, password: String) {

    Auth.auth().signIn(withEmail: email, password: password) { [weak self] user, error in

        print("Signed In")

        if(error != nil) {
            print("Failed to login")

            self!.failedToLogin = true
            self!.errorMessage = ("\(String(describing: error))")
            print(error!)
            return
        } else if error == nil {
            print("Success Logging In")

        }
    }
}

AppView определяет, какое представление загружается в зависимости от того, вошел ли пользователь в систему.

AppView

        if !userStore.isLoggedIn {
            LoginView().transition(.opacity)
        }

        if userStore.isLoggedIn  {
            ContentView().transition(.opacity)
        }

Сообщения об ошибках Atm не отображаются; представление входа в систему также отображается незадолго до основного представления.

Как правильно отобразить сообщения об ошибках в представлении?

1 Ответ

2 голосов
/ 13 февраля 2020

API-интерфейсы Firebase являются асинхронными просто потому, что они обращаются к удаленной системе через inte rnet, что занимает немного времени. Кстати, то же самое касается доступа к локальному диску. Это сообщение в блоге объясняет это более подробно.

Следовательно, userStore.login является асинхронным процессом. Т.е. вызов if self.userStore.failedToLogin выполняется до того, как userStore.login вернется. Таким образом, userStore.failedToLogin по-прежнему false, и код в условном выражении никогда не будет выполнен.

Существует два способа решения этой проблемы:

  1. Реализация замыкающего замыкания на userStore.logIn и перемещение кода, отображающего ошибку, в замыкание
  2. Make userStore.failedToLogin издатель и подпишитесь на видимость вашего оповещения
...