#firebase #google-cloud-firestore #swiftui #swift5
#Firebase #Google-cloud-firestore #SwiftUI #swift5
Вопрос:
Разворачивание значений обычным способом в представлениях SwiftUI запрещено, но вы можете сделать это в пределах body
, скажем, an HStack
или a 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)
}
}
}
}
session
Свойство принадлежит SessionStore
классу и, по сути, является необязательным User
.
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
}
})
}
}
Зарегистрированный пользователь действительно вошел в систему, но я не могу получить доступ к каким-либо свойствам.
Ответ №1:
Установите isLoggedIn точно в том месте, где вы установили UserSession, потому что это выполняется в асинхронном обратном вызове, и сделайте это в основной очереди (для правильного обновления пользовательского интерфейса)
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
}
}
}
Комментарии:
1. мой
session.userSession
по-прежнему равен нулю, и я все еще сбой. Хороший вызовDispatch.main.async
, хотя2. ошибка возникает в моем profileImageUrl, а именно;
session.userSession.profileImageUrl
Ответ №2:
У меня это работает. Не уверен, насколько это масштабируемо, но я делаю not равно нулю. Я также вставил его в кнопку, чтобы переключить его с an onTapGesture
.
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)
}
}
}
}
}
}