I'm following iOS Academy tutorial on a Chat App. In said app, when a user logs in for the first time using Facebook, i need to retrieve the associated email and store it in my database. Lurking at YT comments ( here ) i've found out that a FB account can have no associated email if it was registered with the phone number. Quoting the literal comment:

I created my facebook account without an email (only through a phone number) it still registers the authentication however the identifier is missing. It also does not send out information to the database. Incase anyone who has only a phone has tried.

Since i need to pass the retrieved email to my Firebase Realtime database, i want to handle this issue, but i would need to know what happens when i try to retrieve an email using FBSKDLoginKit API if there is no associated email.

Since my FB has an associated email, and apparently there's no way to remove it and leave the field blank, i tried to register a new FB account with my phone number. The problem is that in order to be able to run the app on test mode and log into FB, i would need to validate it on Facebook For Developers, but to log into Developers i need an associated email. So i'm at a dead end and can't test myself.

My question is: does anyone knows what the email result returns in a FB request if there is no associated email?

Here's my code, my guess is that the function hits the return in the guard block at the commented line down below, because the email is equal to nil, but from what i've read on Youtube it seems that only the Database block is skipped while the Firebase authentication succeeds. So maybe it returns an empty string, or something else.

func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {

    guard let token = result?.token?.tokenString else {
        return
    }
    
    let facebookRequest = FBSDKLoginKit.GraphRequest(graphPath: "me",
                                                     parameters: ["fields" : "email, first_name"], tokenString: token,
                                                     version: nil,
                                                     httpMethod: .get)

    facebookRequest.start { [weak self] _, result, error in
        
        guard let result = (result as? [String: Any]), error == nil else {
            self?.alertUserLoginError(message: "An error occurred while processing your request. Please try to sign in using Google.")
            return
        }
        
        guard let firstName = (result["first_name"] as? String),
            let email = (result["email"] as? String) else {
                return
        }


 // Imo here the func returns cause email is equal to nil, but apparently that's not true. 
 // The database block is skipped, but the auth block down below is not. 


     DatabaseManager.shared.insertUser(with: chatUser, completion: { success in 
  
 // Doing other unrelated stuff

     }
       

  // The following block is run apparently, not sure why

    
        let credential = FacebookAuthProvider.credential(withAccessToken: token)

        FirebaseAuth.Auth.auth().signIn(with: credential) { authResult, error in
            
            
            guard authResult != nil, error == nil else {
                FBSDKLoginKit.LoginManager().logOut()
                return
            }         
        }
    }
}

This is the database function in DatabaseManager class, called up above:

     public func insertUser(with user: ChatAppUser, completion: @escaping (Bool) -> Void) {
    database.child(user.safeEmail).setValue([
        "first_name" : user.firstName
    ],
    withCompletionBlock: { error, _ in
        guard error == nil else {
            completion(false)
            return
        }
        completion(true)
    })
}
1

There are 1 answers

2
henna patodiya On
func FacebookGETDataClicked(_ sender: Any)
{
    let fbLoginManager : LoginManager = LoginManager()
    fbLoginManager.logIn(permissions: ["email"], from: self) { (result, error) in
        if (error == nil){
            let fbloginresult : LoginManagerLoginResult = result!
            let fbloginresultsss: Set<String> = fbloginresult.grantedPermissions
            let arr = [String](fbloginresultsss)
            
            if arr.count > 0 {
                if(arr.contains("email"))
                {
                    self.getFBUserData()
                    fbLoginManager.logOut()
                }
            }
        }
    }
}

func getFBUserData(){
    var userProfileImage = String()
    var useremail = String()
    var userFullName = String()
    var userID = String()

    if((AccessToken.current) != nil){
    GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name,last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) in
        if (error == nil) {
            let dict = result as! [String : AnyObject]
            print(dict)
      
            if let mail = (dict["email"] as? String)
            {
                useremail = mail
            }
            
            if let name = (dict["name"] as? String)
            {
                userFullName = name
            }
            
            if let id = (dict["id"] as? String)
            {
                userID = id
            }
            
            if let pic = dict["picture"] as? NSDictionary
            {
                let profilePictureObj = pic
                
                let datas = profilePictureObj["data"] as! NSDictionary
                userProfileImage  = datas["url"] as! String
            }
            
            print(userID,useremail,userFullName,userProfileImage)
        }
        
    })
}

}