Google cloud firestore 在Firebase-SwiftUI中使用DispatchQueue更新UI
我正在尝试使用Google cloud firestore 在Firebase-SwiftUI中使用DispatchQueue更新UI,google-cloud-firestore,swiftui,grand-central-dispatch,swift5,Google Cloud Firestore,Swiftui,Grand Central Dispatch,Swift5,我正在尝试使用DispatchQueue更新我的UI,这样当Firebase对用户进行身份验证时,我可以将新创建的数据传递到下一个屏幕 我有一个SignUpView,它注册了一个用户,然后在成功后转到ProfileView。ProfileView允许用户为应用程序添加更具体的细节 我有一个userSession对象,它成功地让用户登录,但不会在下一个屏幕上立即更新UI。这可能是因为我没有正确使用DispatchQueue.main.async,我无法在SwiftUI中的视图的主体中使用它 这里有
DispatchQueue
更新我的UI,这样当Firebase对用户进行身份验证时,我可以将新创建的数据传递到下一个屏幕
我有一个SignUpView
,它注册了一个用户,然后在成功后转到ProfileView
。ProfileView
允许用户为应用程序添加更具体的细节
我有一个userSession
对象,它成功地让用户登录,但不会在下一个屏幕上立即更新UI。这可能是因为我没有正确使用DispatchQueue.main.async
,我无法在SwiftUI中的视图的主体中使用它
这里有一个视图
我用来填充从注册视图
获得的档案视图
中的用户名
struct ProfileView: View {
@EnvironmentObject var session: SessionStore
@ObservedObject var profileViewModel = ProfileViewModel()
@ObservedObject var signUpViewModel = SignUpViewModel()
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1)).edgesIgnoringSafeArea(.all)
ZStack(alignment: .top) {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1))
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.edgesIgnoringSafeArea(.bottom)
ScrollView(.vertical, showsIndicators: false) {
VStack {
ProfileHeaderView(signUpViewModel: signUpViewModel)
VitalsHeaderView(signUpViewModel: signUpViewModel)
ShareProfileView(profileViewModel: profileViewModel)
}
.padding(.top, 30)
}
}
}
.navigationBarHidden(true)
.navigationBarTitle("")
}
}
注意:当我转到HomeView时,会显示用户名和其他重要信息。我认为这是因为此时数据库已更新,我可以开始读取值。
struct VitalsHeaderView: View {
@EnvironmentObject var session: SessionStore
var body: some View {
VStack {
if session.isLoggedIn {
Text(session.userSession!.username)
.font(.system(size: 20, weight: .bold))
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
}
}
.padding(.top, 30)
.padding(.leading, 30)
}
}
下面,你会看到一个坏的黑客,它不起作用,但这正是我想要做的。如何使用调度队列更新UI
struct VitalsHeaderView: View {
@EnvironmentObject var session: SessionStore
@ObservedObject var signUpViewModel = SignUpViewModel()
func updateUI() {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.session.isLoggedIn = true
}
}
var body: some View {
VStack {
if session.isLoggedIn {
Button(action: updateUI) {
Text(session.userSession!.username)
.font(.system(size: 20, weight: .bold))
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
}
}
}
.padding(.top, 30)
.padding(.leading, 30)
}
}
已更新
这是我的SessionStore
code
import Foundation
import Combine
import Firebase
class SessionStore: ObservableObject {
@Published var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: "isLoggedIn") {
didSet {
UserDefaults.standard.set(self.isLoggedIn, forKey: "isLoggedIn")
}
}
var userSession: User?
var handle: AuthStateDidChangeListenerHandle?
func listenAuthenticationState() {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if let user = user {
print(user.email as Any)
let firestoreUserId = Ref.FIRESTORE_DOCUMENT_USERID(userId: user.uid)
firestoreUserId.getDocument { (document, error) in
if let dict = document?.data() {
guard let decodeUser = try? User.init(fromDictionary: dict) else { return }
DispatchQueue.main.async {
self.userSession = decodeUser
self.isLoggedIn = true
}
}
}
} else {
self.isLoggedIn = false
self.userSession = nil
}
})
}
func logout() {
do {
try Auth.auth().signOut()
} catch {
}
}
func unbind() {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
deinit {
unbind()
}
}
我在ProfileView
中初始化vitalheaderview
,它是vitalheaderview
上面的一个结构
struct ProfileView: View {
@EnvironmentObject var session: SessionStore
@ObservedObject var profileViewModel = ProfileViewModel()
@ObservedObject var signUpViewModel = SignUpViewModel()
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1)).edgesIgnoringSafeArea(.all)
ZStack(alignment: .top) {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1))
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.edgesIgnoringSafeArea(.bottom)
ScrollView(.vertical, showsIndicators: false) {
VStack {
ProfileHeaderView(signUpViewModel: signUpViewModel)
VitalsHeaderView(signUpViewModel: signUpViewModel)
ShareProfileView(profileViewModel: profileViewModel)
}
.padding(.top, 30)
}
}
}
.navigationBarHidden(true)
.navigationBarTitle("")
}
}
注意:我刚刚添加(并测试)将signUpViewModel属性添加到Vitals Header视图中,仍然没有任何内容您是否可以为会话存储添加代码,以及如何初始化VitalHeaderView
?您需要确保SessionStore
符合协议,并且isLoggedIn
是@已发布
变量。@Zorayr已完成<代码>会话存储
符合可观察对象
。这就是你所说的礼节吗?也,isLoggedIn
确实是一个@Published
属性。您是否也可以为会话存储添加代码,以及如何初始化vitalheaderview
?您需要确保SessionStore
符合协议,并且isLoggedIn
是一个@Published
变量。@Zorayr完成了<代码>会话存储符合可观察对象
。这就是你所说的礼节吗?而且,isLoggedIn
确实是一个@已发布的
属性。