打开包装时非零用户崩溃-Firebase,SwiftUI

打开包装时非零用户崩溃-Firebase,SwiftUI,firebase,google-cloud-firestore,swiftui,swift5,Firebase,Google Cloud Firestore,Swiftui,Swift5,不允许在SwiftUI视图中以常规方式展开值,但您可以在主体内展开,例如HStack或VStack。下面我正在尝试打开一个用户,我确信它不是零。MyLoginView允许用户在Firebase Firestore上创建帐户,如果用户输入了正确的值,则让您登录,如果用户输入的值不正确,则显示警报视图 在我的HomeView.swift(启动后的第一个屏幕)中,我试图显示用户图像时崩溃。但是,当我打开该用户时,该用户在控制台中仍然为零。我认为这是因为Firebase在视图初始化之前没有时间加载图像。

不允许在SwiftUI视图中以常规方式展开值,但您可以在
主体
内展开,例如
HStack
VStack
。下面我正在尝试打开一个用户,我确信它不是零。My
LoginView
允许用户在Firebase Firestore上创建帐户,如果用户输入了正确的值,则让您登录,如果用户输入的值不正确,则显示警报视图

在我的
HomeView.swift
(启动后的第一个屏幕)中,我试图显示用户图像时崩溃。但是,当我打开该用户时,该用户在控制台中仍然为零。我认为这是因为Firebase在视图初始化之前没有时间加载图像。但我可能错了。救命啊


struct HomeProfileView: View {
    @EnvironmentObject var session: SessionStore
    @State var showDashboard = false
    var user: User?
    
    var body: some View {
        if user != nil {
            URLImage(URL(string: user!.profileImageUrl)!, content: {
                $0.image
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .clipShape(Circle())
            })
            .frame(width: 50, height: 50)
            .background(Color(#colorLiteral(red: 0.9490196078, green: 0.9490196078, blue: 0.9490196078, alpha: 1)))
            .clipShape(Circle())
            .shadow(color: Color.black.opacity(0.1), radius: 1, x: 0, y: 1)
            .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 10)
            .sheet(isPresented: $showDashboard) {
                DashboardView(showDashboard: $showDashboard)
            }
        }
    }
}


我不认为我需要一个可选的用户,但我不知道如何安全地打开用户,否则。另一个版本使用会话
EnvironmentObject
访问当前登录的用户


struct HomeProfileView: View {
    @EnvironmentObject var session: SessionStore
    @State var showDashboard = false
    
    var body: some View {
        if session.isLoggedIn {
            URLImage(URL(string: session.userSession!.profileImageUrl)!, content: {
                $0.image
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .clipShape(Circle())
            })
            .frame(width: 50, height: 50)
            .background(Color(#colorLiteral(red: 0.9490196078, green: 0.9490196078, blue: 0.9490196078, alpha: 1)))
            .clipShape(Circle())
            .shadow(color: Color.black.opacity(0.1), radius: 1, x: 0, y: 1)
            .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 10)
            .sheet(isPresented: $showDashboard) {
                DashboardView(showDashboard: $showDashboard)
            }
        }
    }
}


会话
属性属于
会话存储
类,本质上是可选的
用户


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 }
                        self.userSession = decodeUser
                    }
                }
                self.isLoggedIn = true
            } else {
                print("User is Logged Out")
                self.isLoggedIn = false
                self.userSession = nil
            }
        })
    }
}


登录的用户确实已登录,但我无法访问任何属性。

在设置userSession的位置准确设置isLoggedIn,因为它是在异步回调中完成的,并在主队列上执行此操作(以正确更新UI)


我有这个工作。不确定它的可扩展性,但我正在做一个不等于零的测试。我还将它放在一个按钮中,与
ontapsignate
进行切换


struct HomeProfileView: View {
    @EnvironmentObject var session: SessionStore
    @State var showDashboard = false
    
    var body: some View {
        if session.isLoggedIn {
            if (session.userSession?.profileImageUrl) != nil {
                Button(action: { self.showDashboard.toggle() } ) {
                    URLImage(URL(string: session.userSession!.profileImageUrl)!, content: {
                        $0.image
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .clipShape(Circle())
                    })
                    .frame(width: 50, height: 50)
                    .background(Color(#colorLiteral(red: 0.9490196078, green: 0.9490196078, blue: 0.9490196078, alpha: 1)))
                    .clipShape(Circle())
                    .shadow(color: Color.black.opacity(0.1), radius: 1, x: 0, y: 1)
                    .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 10)
                    .sheet(isPresented: $showDashboard) {
                        DashboardView(showDashboard: $showDashboard)
                    }
                }
            }
        }
    }
}



我的
session.userSession
仍然为零,我仍在崩溃。调用
Dispatch.main.async
很好,尽管错误发生在我的profileImageUrl上,即<代码>会话.userSession.profileImageUrl

struct HomeProfileView: View {
    @EnvironmentObject var session: SessionStore
    @State var showDashboard = false
    
    var body: some View {
        if session.isLoggedIn {
            if (session.userSession?.profileImageUrl) != nil {
                Button(action: { self.showDashboard.toggle() } ) {
                    URLImage(URL(string: session.userSession!.profileImageUrl)!, content: {
                        $0.image
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .clipShape(Circle())
                    })
                    .frame(width: 50, height: 50)
                    .background(Color(#colorLiteral(red: 0.9490196078, green: 0.9490196078, blue: 0.9490196078, alpha: 1)))
                    .clipShape(Circle())
                    .shadow(color: Color.black.opacity(0.1), radius: 1, x: 0, y: 1)
                    .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 10)
                    .sheet(isPresented: $showDashboard) {
                        DashboardView(showDashboard: $showDashboard)
                    }
                }
            }
        }
    }
}