Dyl*_*lan 15 ios swift swiftui
我正在创建一个包含 Firebase 的 SwiftUI 应用程序以启用登录帐户,非常简单,只是一个带有密码和电子邮件字段的 ui 表单,然后是一个提交按钮。用户登录后,我将 firebase 用户对象存储在 EnvironmentObject 中,以便其余视图可以访问它。该应用程序目前的问题是,一旦用户登录并且用户数据存储在 EnvironmentObject 中,视图应该更新到更改后的状态以显示不同的屏幕,但似乎视图仍然认为 EnvironmentObject等于零。视图不会像它们对状态变量那样自动更改为 EnvironmentObject 中的更新吗?
我已经确保 EnvironmentObject 设置正确并传递给预览和 SceneDelegate
通过在登录时将帐户信息打印到控制台来确保应用程序确实成功登录了用户,但视图本身只会为帐户信息显示 nil,它似乎不会使用用户信息访问更新的 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
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在视图中看到的那样,它应该在用户未登录时呈现登录字段,而当用户登录时,视图应显示另一个视图。其他视图没有显示。
Tob*_*ink 25
尝试使用@Published 属性。尝试实现这样的事情:
class SessionStore : ObservableObject {
@Published var session: User
}
class User: ObservableObject {
@Published var uid: String
@Published var email: String?
@Published var displayName: String?
init(uid: String, displayName: String?, email: String?) {
self.uid = uid
self.email = email
self.displayName = displayName
}
}
Run Code Online (Sandbox Code Playgroud)
当 User 对象发生更改时,这应该会更新您的视图,例如电子邮件或显示名称,因为它们已发布。希望这会有所帮助,gl
更新:
因为 SwiftUI 还不支持嵌套的 Observables,你需要自己通知你的主模型。
请参阅此代码段如何在 ObservableObject 中使用嵌套的 ObservableObject:
class Submodel1: ObservableObject {
@Published var count = 0
}
class Submodel2: ObservableObject {
@Published var count = 0
}
class Model: ObservableObject {
@Published var submodel1: Submodel1 = Submodel1()
@Published var submodel2: Submodel2 = Submodel2()
var anyCancellable: AnyCancellable? = nil
var anyCancellable2: AnyCancellable? = nil
init() {
anyCancellable = submodel1.objectWillChange.sink { (_) in
self.objectWillChange.send()
}
anyCancellable2 = submodel2.objectWillChange.sink { (_) in
self.objectWillChange.send()
}
}
}
Run Code Online (Sandbox Code Playgroud)
当子模型中的数据发生变化时,主模型会通知自己。这将导致视图更新。
如果这对您有帮助,请告诉我.. 祝你好运!
归档时间: |
|
查看次数: |
8171 次 |
最近记录: |