【问题标题】:How to check if email already exist before creating an account (Swift)如何在创建帐户之前检查电子邮件是否已经存在(Swift)
【发布时间】:2019-07-31 01:01:25
【问题描述】:

我知道有人问过这个问题的不同变体。但是,我似乎每次都遇到同样的问题。

我想在用户推送到下一个视图之前检查电子邮件是否已经存在。我将输入数据库中存在的电子邮件,并且始终调用 performSegue 函数并推送用户,就好像该电子邮件不存在一样。

我可以正式检查的唯一方法是当用户到达最终注册 VC 并且Auth.auth().createUser(withEmail: email as! String, password: password as! String ) { (user, error) in 代码将检查所有错误。

但是,为了获得良好的用户体验,我不希望用户必须点击返回三次才能更改电子邮件地址。这是我用于输入电子邮件视图控制器的代码。

   // Check if email is already taken
        Auth.auth().fetchSignInMethods(forEmail: emailTextField.text!, completion: { (forEmail, error) in
                // stop activity indicator
                self.nextButton.setTitle("Continue", for: .normal)
                self.activityIndicator.stopAnimating()


                if let error = error {
                    print("Email Error: \(error.localizedDescription)")
                    print(error._code)
                    self.handleError(error)
                    return

                } else {
                    print("Email is good")
                    self.performSegue(withIdentifier: "goToCreateUsernameVC", sender: self)

                }

        })

首先,我是否在 forEmail 部分输入了 create 属性?我添加了emailTextField.text,因为这是我知道如何获取用户输入的电子邮件的唯一方法。有谁知道我可以做到这一点的更好方法?

【问题讨论】:

  • 给我一分钟,我可以和你分享一些代码
  • 这是一个注册视图控制器,而不是我假设的登录视图控制器?
  • @DavidChopin 是的,这是一个注册视图控制器。谢谢!
  • 哦,等等,我刚刚意识到您只是想知道是否有办法检查电子邮件是否存在。让我补充一下我是如何做到这一点的。
  • 我现在明白了,我实际上正在处理类似的事情。答案是使用电子邮件属性将用户对象存储在 Firebase 数据库中并在最终移动到实际创建用户帐户的 VC 之前对其进行查询

标签: swift firebase firebase-realtime-database firebase-authentication


【解决方案1】:

我如何创建用户帐户

这是我使用的一个例子。当用户提供凭据时,FirebaseAuth 会检查这些凭据是否可用于创建用户帐户。该函数返回两个值,一个表示创建是否成功的布尔值,一个可选的错误,当创建不成功时返回。如果布尔值返回 true,我们只需推送到下一个视图控制器。否则,我们会显示错误。

func createUserAcct(completion: @escaping (Bool, Error?) -> Void) {

    //Try to create an account with the given credentials
    Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordConfirmTextField.text!) { (user, error) in
        if error == nil {

            //If the account is created without an error, then we will make a ProfileChangeRequest, i.e. update the user's photo and display name.
            if let firebaseUser = Auth.auth().currentUser {

                let changeRequest = firebaseUser.createProfileChangeRequest()
                //If you have a URL for FirebaseStorage where the user has uploaded a profile picture, you'll pass the url here
                changeRequest.photoURL = URL(string: "nil")
                changeRequest.displayName = self.nameTextField.text!
                changeRequest.commitChanges { error in
                    if let error = error {
                        // An error happened.
                        completion(false, error)
                    } else {
                        //If the change is committed successfully, then I create an object from the credentials. I store this object both on the FirebaseDatabase (so it is accessible by other users) and in my user defaults (so that the user doesn't have to remotely grab their own info

                        //Create the object
                        let userData = ["email" : self.emailTextField.text!,"name": self.nameTextField.text!] as [String : Any]

                        //Store the object in FirebaseDatabase
                        Database.database().reference().child("Users").child(firebaseUser.uid).updateChildvalues(userData)
                        //Store the object as data in my user defaults
                        let data = NSKeyedArchiver.archivedData(withRootObject: userData)
                        UserDefaults.standard.set(data, forKey: "UserData")
                        UserDefaults.standard.set([Data](), forKey: "UserPhotos")
                        completion(true, nil)
                    }
                }
            }
        } else {
            // An error happened.
            completion(false, error)
        }
    }
}

这是我如何使用它的示例。我们可以使用返回的成功布尔值来确定我们是否应该推送到下一个视图控制器,或者向用户显示错误警报。

createUserAcct { success, error in
    //Handle the success
    if success {
        //Instantiate nextViewController
        let storyboard = UIStoryboard(name: "Main", bundle: .main)
        let nextVC = storyboard.instantiateViewController(withIdentifier: "NextVC") as! NextViewController

        //Push typeSelectVC
        self.navigationController!.pushViewController(viewController: nextVC, animated: true, completion: {
            //We are no longer doing asynchronous work, so we hide our activity indicator
            self.activityIndicator.isHidden = true
            self.activityIndicator.stopAnimating()
        })
    } else {
        //We now handle the error
        //We are no longer doing asynchronous work, so we hide our activity indicator
        self.activityIndicator.isHidden = true
        self.activityIndicator.stopAnimating()

        //Create a UIAlertController with the error received as the message (ex. "A user with this email already exists.")
        let alertController = UIAlertController(title: "Error", message: error!.localizedDescription, style: .alert)
        let ok = UIAlertAction(title: "OK", style: .cancel, action: nil)

        //Present the UIAlertController
        alertController.addAction(ok)
        self.present(alertController, animated: true, completion: nil)
    }

}

如果这一切都有意义,请告诉我,我知道其中有很多。我只是在考虑你可能会发现你需要完成但你可能不知道的事情(比如提出更改请求,或在 FirebaseDatabase 上存储数据对象)。

现在检查电子邮件是否已被占用:

还记得我说过我在创建帐户时将用户对象发布到FirebaseDatabase 吗?好吧,我们可以查询给定的电子邮件以查看它是否已经存在。如果没有,我们将继续正常流程,而无需实际创建帐户。否则,我们只是告诉用户选择另一个电子邮件地址。

将用户对象推送到您的数据库(取自上述代码):

if let firebaseUser = Auth.auth().currentUser {
    //Create the object
    let userData = ["email" : self.emailTextField.text!,"name": self.nameTextField.text!] as [String : Any]

    //Store the object in FirebaseDatabase
    Database.database().reference().child("Users").child(firebaseUser.uid).updateChildvalues(userData)
}

现在查询是否有人已经拥有该电子邮件:

func checkIfEmailExists(email: String, completion: @escaping (Bool) -> Void ) {

    Database.database().reference().child("Users").queryOrdered(byChild: "email").queryEqual(toValue: email).observeSingleEvent(of: .value, with: {(snapshot: DataSnapshot) in

        if let result = snapshot.value as? [String:[String:Any]] {
            completion(true)
        } else {
            completion(false)
        }
    }
}

那么我们可以这样称呼它:

checkIfEmailExists(email: emailTextField.text!, completion: {(exists) in 
    if exists {
        //Present error that the email is already used
    } else {
        //Segue to next view controller
    }
})

【讨论】:

  • 是的,效果很好。我怀疑这与查询有关,但我不知道处理它的最佳方法。已接受答案。
  • 如果您有任何问题,请让我知道
  • 肯定会,看起来你肯定对我正在从事的项目类型有经验。将再次伸出援手!
猜你喜欢
  • 2017-07-11
  • 2019-05-30
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 2011-12-02
相关资源
最近更新 更多