在 SwiftUI 中使用 Firebase Auth 登录后如何检查用户是否已存在于 Firestore 集合中

Gio*_*dze 1 firebase swift google-cloud-firestore swiftui

@Published var isNewUser: Bool?

init() {
  self.isNewUser = false
}

func checkIfTheUserExistsInDataBase(
  userID: String?, completion: @escaping (_ isNewuser: Bool) -> Void
) {
  let docRef = db.collection("users").whereField("user_id", isEqualTo: userID!).limit(to: 1)
  docRef.getDocuments { querySnapshot, error in
    if error != nil {
      print(error?.localizedDescription)
    } else {
      if let doc = querySnapshot?.documents, doc.isEmpty {
        completion(true)
      } else {
        completion(false)
      }
    }
  }
}

func login(
  email: String, password: String,
  completion: @escaping (_ error: Error?, _ isEmailVerified: Bool) -> Void
) {
  Auth.auth().signIn(withEmail: email, password: password) { authDataResult, error in
    if error == nil {
      if authDataResult!.user.isEmailVerified {
        DispatchQueue.main.async {
          self.checkIfTheUserExistsInDataBase(userID: authDataResult?.user.uid) { isNewUser in
            self.isNewUser = isNewUser
          }
        }
        UserDefaults.standard.set(authDataResult?.user.uid, forKey: CurrentUserDefaults.userID)
        completion(error, true)
      } else {
        print("Email not verified")
        completion(error, false)
      }
    } else {
      completion(error, false)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用DispatchSemaphore让运行时间较长的函数首先执行checkIfTheUserExistsInDataBase,但它冻结了我的应用程序。有一个更好的方法吗?

Pet*_*ese 6

Firebase 支持 async/await(请参阅我创建的这个短片、这个视频和这篇博文来详细解释这一点。

要回答您的问题:您应该使用 async/await 来调用用户签名、等待结果、检查用户是否存在于您的 Firestore 集合中以及更新 UI。

以下代码片段(基于此示例应用)使用 Firestore 中的新COUNT功能来计算集合中的文档数量,users以确定是否至少有一个用户具有刚刚登录的用户的 ID。

func isNewUser(_ user: User) async -> Bool {
  let userId = user.uid
  let db = Firestore.firestore()
  let collection = db.collection("users")
  let query = collection.whereField("userId", isEqualTo: userId)
  let countQuery = query.count
  do {
    let snapshot = try await countQuery.getAggregation(source: .server)
    return snapshot.count.intValue >= 0
  }
  catch {
    print(error)
    return false
  }
}

func signInWithEmailPassword() async -> Bool {
  authenticationState = .authenticating
  do {
    let authResult = try await Auth.auth().signIn(withEmail: self.email, password: self.password)
    if await isNewUser(authResult.user) {

    }
    return true
  }
  catch  {
    print(error)
    errorMessage = error.localizedDescription
    authenticationState = .unauthenticated
    return false
  }
}

Run Code Online (Sandbox Code Playgroud)

请参阅此视频,了解有关如何在 SwiftUI 应用中实施 Firebase 身份验证的更多详细信息。