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
确实是一个
@已发布的
属性。