Swift iOS Firebase - 如果FirebaseAuth.FIRUser对象不是nil,它上面的.email怎么可能返回nil?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift iOS Firebase - 如果FirebaseAuth.FIRUser对象不是nil,它上面的.email怎么可能返回nil?相关的知识,希望对你有一定的参考价值。

我使用Firebase的电子邮件/密码登录方法为用户创建帐户。使用该方法,用户必须拥有一个电子邮件地址才能通过Firebase进行身份验证。

FirebaseAuth有一个名为FIRUserUser对象

enter image description here

当用户首次创建帐户或登录回调中的现有帐户时,User对象将被初始化:

创建帐号:

Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: {
            (user, error) in

            // user's auth credentials are now created but user can still be nil

登录现有帐户:

Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: {
            (user, error) in

            // user's auth credentials are now accessed but user can still be nil

User对象有一个.email可选的String类型,包含用户的电子邮件地址。

enter image description here

我使用单例类来管理通过Firebase发生的所有事情,在上面的两种情况下,当User对象被初始化时,我将数据传递给我的Firebase单例的类属性。我知道User对象可以返回为nil所以我运行if-let以确保它不是。

我的问题是如果使用电子邮件/密码登录方法如果User对象在回调中不是nil,那么.email可能是零,即使有必要让它创建一个帐户或登录?

在我运行if-let语句之后,我使用guard语句检查并查看.email是否不是nil但似乎它可以在FirebaseSingleton属性初始化之前运行(这意味着它将为nil)或者它可能是不必要的保证User对象返回一个值。

顺便说两下,用户创建和帐户或登录emailTextFiled并且passwordTextField不会是nil。我运行空格,.isEmpty和!= nil检查它们。

我的代码:

class FirebaseSingleton{

    static let sharedInstance = FirebaseSingleton()

    var dbRef: DatabaseReference? = Database.database().reference()
    var storageDbRef: StorageReference? = Storage.storage().reference(forURL: "gs://blablabla.appspot.com")
    var currentUser: User? = Auth.auth().currentUser
    var currentUserID: String? = Auth.auth().currentUser?.uid
    var currentUserEmail: String? = Auth.auth().currentUser?.email
    var currentUserPhotoUrl: URL? = Auth.auth().currentUser?.photoURL
    var currentUserDisplayName: String? = Auth.auth().currentUser?.displayName
}

创建帐户:

Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: {
                (user, error) in

                if error != nil { return }

                if let user = user{

                    let sharedInstance = FirebaseSingleton.sharedInstance
                    sharedInstance.currentUser = user
                    sharedInstance.currentUserID = user.uid
                    sharedInstance.currentUserEmail = user.email // at this point is it possible for this to be nil?
                    sharedInstance.currentUserPhotoUrl = user.photoURL
                    sharedInstance.currentUserDisplayName = user.displayName
                }else{
                   return
                }

                // is this guard statement necessary?
                guard let email = user.uid else { return }
})

登录现有帐户:

Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: {
                (user, error) in

                if error != nil { return }

                if let user = user{

                    let sharedInstance = FirebaseSingleton.sharedInstance
                    sharedInstance.currentUser = user
                    sharedInstance.currentUserID = user.uid
                    sharedInstance.currentUserEmail = user.email // at this point is it possible for this to be nil?
                    sharedInstance.currentUserPhotoUrl = user.photoURL
                    sharedInstance.currentUserDisplayName = user.displayName
                }else{
                   return
                }

                // is this guard statements necessary?    
                guard let email = user.uid else { return }
})
答案

不确定你究竟要求什么(因为对我来说看起来更像是一个快速问题而不是firebase问题),但只要用户不是nil,uid属性就不是可选的(String)所以user.uid将永远不会是零。这是一个String?的电子邮件是不一样的因此可能或不是nil

另一答案

在与@Benjamin Jimenez和@kbunarjo建议进行了一次调情后,我做了一些思考,并意识到Firebase还有一个电话登录方法。如果它已启用且用户选择它作为其登录方法,那么.email地址将为零,因为没有用于创建帐户的电子邮件地址。

enter image description here

对于我的情况,因为我使用电子邮件/密码登录方法,然后.email不应该是零,因为它是创建帐户的唯一方法。但正如用户可以在完成处理程序中返回nil(即使使用正确的电子邮件和密码),也许电子邮件地址也可以返回为零,因为它是可选的。

据说最安全的方法是另一个if-let来检查user.email是不是nil,如果出于某种奇怪的原因,那么它就是使用输入到emailTextField中的电子邮件地址作为替代。输入emailTextField和密码组合的电子邮件地址必须正确,否则用户将无法通过Firebase进行身份验证并输出错误!= nil。

Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: {
                (user, error) in

                // if the email address and/or password are incorrect then error != nil and the code below this wont run
                if error != nil { return }

                if let user = user{

                    let sharedInstance = FirebaseSingleton.sharedInstance
                    sharedInstance.currentUser = user
                    sharedInstance.currentUserID = user.uid
                    sharedInstance.currentUserPhotoUrl = user.photoURL
                    sharedInstance.currentUserDisplayName = user.displayName

                    // instead of the guard statement I use another ‘if-let’ if for some reason .email is nil
                    if let currentUserEmail = user.email {
                              sharedInstance.currentUserEmail = currentUserEmail
                         }else{
                              sharedInstance.currentUserEmail = self.emailTextField.text! // the email address entered into here has to be valid otherwise it would've never made it to this point
                    }
                }else{
                   return
                }
})

如果创建帐户,请使用相同的确切代码进行回调

由于@rMickeyD注意到Facebook登录方法也不会使用电子邮件地址。我从来没用过它所以我没有把它包括在内。基本上,如果其他登录方法都没有使用您的电子邮件地址,那么user.email将为零。即使我有匿名登录作为选项,使用匿名登录的方法也不需要电子邮件地址或密码,因此可以理解电子邮件将是零。

您应该检查文档以查看是否需要该电子邮件以用于所有其他登录方法,但电话号码不需要它。

以上是关于Swift iOS Firebase - 如果FirebaseAuth.FIRUser对象不是nil,它上面的.email怎么可能返回nil?的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 自定义声明 IOS 和 swift

Swift/iOS - Firebase 远程配置获取值永远不会完成

FIREBASE 数据库 - 将唯一密钥存储到子节点(Swift/IOS)

Firebase Auth.auth().createUser 方法跳过 ios, swift

Firebase.google.com iOS 中的 Firebase 动态链接(Swift)

新的 Firebase 数据导致 TableView 单元格闪烁 (Firebase/iOS/Swift)