Я создаю приложение SwiftUI, которое включает в себя Firebase, чтобы включить вход в учетную запись, очень просто, просто пользовательский интерфейс с полями пароля и электронной почты, а затем кнопку для отправки. Как только пользователь войдет в систему, я сохраню пользовательский объект firebase в EnvironmentObject, так что остальные виды будут иметь к нему доступ. Проблема с приложением в настоящее время заключается в том, что после входа пользователя в систему и сохранения пользовательских данных в EnvironmentObject представление должно обновиться до измененного состояния, чтобы отобразить другой экран, но, похоже, представление все еще думает, что EnvironmentObjectравно нулю. Разве представления не изменяются автоматически на обновления в EnvironmentObject, как это происходит для переменных состояния, возможно?
Я убедился, что EnvironmentObject настроен правильно и передан как в предварительный просмотр, так и в SceneDelegate
Убедитесь, что приложение действительно успешно выполняет вход в систему пользователя, распечатав информацию об учетной записи на консоли послевойдите в систему, но само представление будет отображать только ноль для информации об учетной записи, кажется, что оно не получит доступ к обновленному EnvironmentObject с информацией о пользователе
import SwiftUI
import Firebase
import Combine
struct ContentView: View {
@EnvironmentObject var session: SessionStore
@State var emailTextField: String = ""
@State var passwordTextField: String = ""
@State var loading = false
@State var error = false
var body: some View {
VStack {
if (session.session != nil) {
Home()
} else {
Form {
TextField("Email", text: $emailTextField)
SecureField("Password", text: $passwordTextField)
Button(action: signIn) {
Text("Sign in")
}
}
Text("Session: \(session.session?.email ?? "no user")")
}
}.onAppear(perform: getUser)
}
func getUser () {
session.listen()
}
func signIn () {
loading = true
error = false
session.signIn(email: emailTextField, password: passwordTextField) { (result, error) in
self.loading = false
if error != nil {
self.error = true
} else {
self.emailTextField = ""
self.passwordTextField = ""
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(SessionStore())
}
}
class SessionStore : ObservableObject {
var didChange = PassthroughSubject<SessionStore, Never>()
var session: User? { didSet { self.didChange.send(self) }}
var handle: AuthStateDidChangeListenerHandle?
func listen () {
// monitor authentication changes using firebase
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if let account = user {
// if we have a user, create a new user model
print("Got user: \(account)")
self.session = User(
uid: account.uid,
displayName: account.displayName,
email: account.email
)
print("Session: \(self.session?.email ?? "no user")")
} else {
// if we don't have a user, set our session to nil
self.session = nil
}
}
}
func signUp(
email: String,
password: String,
handler: @escaping AuthDataResultCallback
) {
Auth.auth().createUser(withEmail: email, password: password, completion: handler)
}
func signIn(
email: String,
password: String,
handler: @escaping AuthDataResultCallback
) {
Auth.auth().signIn(withEmail: email, password: password, completion: handler)
}
func signOut () -> Bool {
do {
try Auth.auth().signOut()
self.session = nil
return true
} catch {
return false
}
}
func unbind () {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
}
class User {
var uid: String
var email: String?
var displayName: String?
init(uid: String, displayName: String?, email: String?) {
self.uid = uid
self.email = email
self.displayName = displayName
}
}
Как вы можете видеть в представлении, предполагается отображать поля входа в систему, когда пользователь не вошел в систему, и когда пользователь вошел в представление, должно отображаться другое представление. Это другое представление не отображается.