Firebase用户邮箱验证状态无法更新问题排查求助
问题描述
创建新用户时会发送邮箱验证邮件,但无法追踪状态变化,无法将Firestore中用户的isEmailVerified字段从false更新为true。调试控制台已确认用户文档存在,但该字段值始终保持false。
相关代码
User 模型
import FirebaseAuth class User: Identifiable { let id: String let username: String let profileImageUrl: String let fullname: String let email: String var stats: UserStats var bio: String? var blocked : Int var reputation : Int var isEmailVerified: Bool var isFollowed = false var isCurrentUser: Bool { return Auth.auth().currentUser?.uid == self.id} init(dictionary: [String: Any]) { self.id = dictionary["uid"] as? String ?? "" self.username = dictionary["username"] as? String ?? "" self.profileImageUrl = dictionary["profileImageUrl"] as? String ?? "" self.fullname = dictionary["fullname"] as? String ?? "" self.email = dictionary["email"] as? String ?? "" self.stats = UserStats(followers: 0, following: 0) self.blocked = dictionary["blocked"] as? Int ?? 0 self.reputation = dictionary["reputation"] as? Int ?? 0 self.isEmailVerified = dictionary["isEmailVerified"] as? Bool ?? false } }
AuthViewModel
class AuthViewModel: ObservableObject { @Published var userSession: Firebase.User? @Published var isAuthenticating = false @Published var error: Error? @Published var user: User? @Published var isLoading = false @Published var isEmailVerified: Bool = false static let shared = AuthViewModel() init() { userSession = Auth.auth().currentUser fetchUser() } func registerUser(email: String, password: String, username: String, fullname: String, profileImage : UIImage) { guard let imageData = profileImage.jpegData(compressionQuality: 0.3) else { return } let filename = NSUUID().uuidString let storageRef = Storage.storage().reference().child(filename) storageRef.putData(imageData, metadata: nil) { _ , error in if let error = error { ProgressHUD.showFailed("Failed to upload image: \(error.localizedDescription)", interaction: false) print("Failed to upload image \(error.localizedDescription)") return } storageRef.downloadURL { url, _ in guard let profileImageUrl = url?.absoluteString else { return } Auth.auth().createUser(withEmail: email, password: password) { result, error in if let error = error { ProgressHUD.showFailed("Error: \(error.localizedDescription)", interaction: false) print("DEBUG: ERROR \(error.localizedDescription)") } guard let user = result?.user else { return } // Send email verification user.sendEmailVerification { error in if let error = error { print("DEBUG: Error sending email verification: \(error.localizedDescription)") } else { print("DEBUG: Email verification sent to \(user.email ?? "")") } } let data = ["email" : email, "username": username.lowercased(), "fullname": fullname, "profileImageUrl": profileImageUrl, "isEmailVerified": false, "uid": user.uid] Firestore.firestore().collection("users").document(user.uid).setData(data) { _ in self.userSession = user self.fetchUser() } } } } } }
ContentView
struct ContentView: View { @State private var isShowing = false @EnvironmentObject var viewModel : AuthViewModel init() { addAuthStateListener() } private func addAuthStateListener() { Auth.auth().addStateDidChangeListener { auth, user in if let user = user { let userRef = Firestore.firestore().collection("users").document(user.uid) userRef.getDocument { (document, error) in if let document = document, document.exists { let data = document.data() let isEmailVerified = data?["isEmailVerified"] as? Bool ?? false print("Текущий статус \(isEmailVerified)") // Check if email is verified and update database if user.isEmailVerified != isEmailVerified { userRef.updateData(["isEmailVerified": user.isEmailVerified]) { error in if let error = error { print("Error updating user document: \(error.localizedDescription)") } else { print("User document updated successfully") } } } } else { print("\(error?.localizedDescription)") } } } } } var body: some View { Group { if viewModel.userSession != nil { if viewModel.isEmailVerified == true {...... } } } }
问题分析与修复方案
核心问题
- ViewModel状态未同步:
AuthViewModel中的isEmailVerified字段始终是初始值false,没有在获取用户数据时更新。 - Firestore更新后未刷新本地数据:在Auth状态监听中更新Firestore文档后,没有同步更新ViewModel的状态,导致视图无法感知变化。
修复步骤
1. 完善AuthViewModel的fetchUser方法
确保获取用户数据时同步更新isEmailVerified:
func fetchUser() { guard let uid = userSession?.uid else { return } Firestore.firestore().collection("users").document(uid).getDocument { snapshot, _ in guard let dictionary = snapshot?.data() else { return } self.user = User(dictionary: dictionary) // 更新本地验证状态 self.isEmailVerified = dictionary["isEmailVerified"] as? Bool ?? false } }
2. 更新Auth状态监听逻辑
在ContentView的监听方法中,更新Firestore后调用fetchUser同步ViewModel数据:
private func addAuthStateListener() { Auth.auth().addStateDidChangeListener { auth, user in guard let user = user else { return } let userRef = Firestore.firestore().collection("users").document(user.uid) userRef.getDocument { (document, error) in guard let document = document, document.exists else { print(error?.localizedDescription ?? "文档不存在") return } let dbVerified = document.data()?["isEmailVerified"] as? Bool ?? false print("当前数据库状态 \(dbVerified)") if user.isEmailVerified != dbVerified { userRef.updateData(["isEmailVerified": user.isEmailVerified]) { error in if let error = error { print("更新文档失败: \(error.localizedDescription)") } else { print("文档更新成功") // 同步更新ViewModel数据 self.viewModel.fetchUser() } } } else { // 状态一致时确保ViewModel数据正确 self.viewModel.isEmailVerified = user.isEmailVerified } } } }
3. 补充用户验证后的状态同步
用户点击验证邮件链接后,Firebase Auth的isEmailVerified状态会更新,但本地需要重新获取用户信息。可以在App启动或用户进入App时自动调用fetchUser,也可以添加手动刷新按钮供用户触发。
额外建议
- 发送验证邮件后,提示用户重启App或手动刷新以同步状态;
- 检查Firestore权限规则,确保用户有权限更新自己的文档;
- 可以在
AuthViewModel中添加手动刷新方法,方便主动触发数据同步。
内容的提问来源于stack exchange,提问作者s1mpledreamer
相关产品推荐
相关产品推荐

