我已经在我的应用程序中设置了我的 Firebase 身份验证来注册用户并保存他们的注册信息,这非常有效。但是,当我尝试获取数据以填充他们的个人资料屏幕(使用他们的姓名、个人资料图片等)时,应用程序崩溃了,说它打开了一个可选值,结果为 nil。我做了一个打印功能,显示信息是否实际上是从 Firestore 中提取的。我不确定为什么每次尝试加载我的个人资料屏幕时它都会崩溃。是我做错了什么还是Auth有问题?
用户型号代码:
import SwiftUI
import Foundation
struct User: Encodable, Decodable{
var uuid: String
var email: String
var profileImageUrl: String
var firstname: String
var lastname: String
}
认证服务
import Foundation
import Firebase
import FirebaseAuth
import FirebaseStorage
import FirebaseFirestore
class AuthService {
static var storeRoot = Firestore.firestore()
static func getUserId(userid: String) -> DocumentReference {
return storeRoot.collection("users").document(userid)
}
static func signUp(firstname: String, lastname:String, email: String, password: String, imageData: Data, onSuccess: @escaping (_ user: User) -> Void, onError: @escaping(_ errorMessage: String) -> Void) {
Auth.auth().createUser(withEmail: email, password: password) {
(authData, error) in
if error != nil {
onError(error!.localizedDescription)
return
}
guard let userId = authData?.user.uid else {return}
let storageProfileUserId = StorageService.storageProfileId(userId: userId)
let metadata = StorageMetadata()
metadata.contentType = "image/jpg"
StorageService.saveProfileImage(userId: userId, firstname: firstname, lastname: lastname, email: email, imageData: imageData, metaData: metadata, storageProfileImageRef: storageProfileUserId, onSuccess: onSuccess, onError: onError)
}
}
static func signIn(email: String, password: String, onSuccess: @escaping (_ user: User) -> Void, onError:
@escaping(_ errorMessage: String) -> Void) {
Auth.auth().signIn(withEmail: email, password: password){
(authData, error) in
if error != nil {
onError(error!.localizedDescription)
return
}
guard let userId = authData?.user.uid else {return}
let firestoreUserId = getUserId(userid: userId)
firestoreUserId.getDocument{
(document, error) in
if let dict = document?.data() {
guard let decodedUser = try? User.init(fromDictionary: dict) else {return}
onSuccess(decodedUser)
}
}
}
}
}
会话存储:
class SessionStore: ObservableObject {
private var db = Firestore.firestore()
var didChange = PassthroughSubject<SessionStore, Never>()
@Published var session: User? {
didSet { self.didChange.send(self) }
}
var handle: AuthStateDidChangeListenerHandle?
func listen() {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if let user = user {
let firestoreUserId = AuthService.getUserId(userid: user.uid)
firestoreUserId.getDocument { (document, error) in
if let dict = document?.data() {
guard let decodedUser = try? User.init(fromDictionary: dict) else { return }
let dataDescription = document?.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
self.session = decodedUser
}
}
} else {
print("User not found")
self.session = nil
}
})
}
func logout() {
do {
try Auth.auth().signOut()
} catch {
}
}
func unbind() {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
deinit {
unbind()
}
}
这是当我尝试解开值时在我的个人资料屏幕上返回错误的代码行:
import SwiftUI
import SDWebImageSwiftUI
struct AccountViewNew: View {
@EnvironmentObject var session: SessionStore
func getUser() {
session.listen()
}
var user: User?
var body: some View {
VStack (alignment: .leading){
HStack {
Text(user?.firstname ?? "Change")
.font(.system(size: 20, weight: .bold, design: .default))
.foregroundColor(Color.white)
.multilineTextAlignment(.leading)
Text(user?.lastname ?? "Your Name")
.font(.system(size: 20, weight: .bold, design: .default))
.foregroundColor(Color.white)
.multilineTextAlignment(.leading)
}
.onAppear(perform: getUser)