Add Facebook "name" to PFUser ["fullname"] in swift - facebook

I have a registration/login method (from PFFacebookUtilsV4) that successfully adds a new PFUser object to my Parse database when a new Facebook user logs in. Within that method I make an FBSDKGraphRequest to get the basic user data (name, email). However I am having trouble adding the name and email to the newly created PFUser object. Here's my code so far:
#IBAction func facebookLogin(sender: AnyObject) {
PFFacebookUtils.logInInBackgroundWithReadPermissions(["public_profile","email","user_friends"], block: { (user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"name,email,picture.width(480).height(480)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
println("Error: \(error)")
ProgressHUD.showError("Error occurred.")
} else {
self.userFullName = result.valueForKey("name") as? String
println("User Name is: \(self.userFullName)")
self.userEmail = result.valueForKey("email") as? String
println("User Email is: \(self.userEmail)")
// Here I try to add the retrieved Facebook data to the PFUser object
user["fullname"] = self.userFullName
user.email = self.userEmail
self.performSegueWithIdentifier("login", sender: self)
println("User signed up and logged in through Facebook!")
ProgressHUD.showSuccess("Welcome \(self.userFullName)!")
}
})
} else {
println("User logged in through Facebook!")
ProgressHUD.showSuccess("Welcome \(self.userFullName)!")
self.performSegueWithIdentifier("login", sender: self)
}
} else {
println("User cancelled the Facebook login.")
}
})
}
Thanks! Any help is greatly appreciated.

Save the user after you add the new data inside the Facebook request closure.
user.saveEventually()
Or any other save that you prefer.

Related

Facebook Auth "An account already exists with the same email address but different sign-in credentials."

I have multiple login options for the user to choose from: email, google, and facebook. If Firebase already has the email stored as a user (ie. the user previously signed up with test#gmail.com), an alert that tells the user that an account with that email already exists. This works perfectly for Google sign in, as shown in this screenshot. However, nothing visually happens when the user clicks the Facebook button (doesn't even switch screens), and I get this error in the debugger:
Error Domain=FIRAuthErrorDomain Code=17012 "An account already exists with
the same email address but different sign-in credentials. Sign in using a
provider associated with this email address." UserInfo={FIRAuthErrorUserInfoNameKey=ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL,
FIRAuthErrorUserInfoEmailKey=318junkjabr#gmail.com,
FIRAuthErrorUserInfoUpdatedCredentialKey=<FIROAuthCredential:
0x6000005f3200>, NSLocalizedDescription=An account already exists with the
same email address but different sign-in credentials. Sign in using a
provider associated with this email address.}
This is my code for the Log In View Controller:
override func viewDidLoad() {
super.viewDidLoad()
setUpFBButton()
setUpGoogleButton()
setUpEmailButton()
GIDSignIn.sharedInstance()?.presentingViewController = self
}
// MARK: - SIGN UP WITH GOOGLE
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let err = error {
print("Failed to log into Google: ", err)
return
}
print("Successfully logged into Google")
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken)
// sign user in with Firebase
Auth.auth().signIn(with: credential, completion: { (user, error) in
let firstName = user?.user.displayName
let email = user?.user.email
let lastName = ""
let uid = user?.user.uid
if let err = error {
print("Failed to create a Firebase User with Google account: ", err)
return
} else {
// Successfully logged in
print("Successfully logged into Firebase with Google email: ", email ?? "", "Now add user to Firestore if user is new.")
// check if user already exists
self.addUserToFirestore(firstName ?? "", lastName, email ?? "", uid ?? "", "Google")
}
})
}
fileprivate func setUpGoogleButton() {
Utilities.styleLightFilledButton(signInGoogleButton)
signInGoogleButton!.addTarget(self, action:
#selector(handleCustomGoogleSignIn), for: .touchUpInside)
GIDSignIn.sharedInstance()?.delegate = self
}
#objc func handleCustomGoogleSignIn() {
GIDSignIn.sharedInstance().signIn()
}
// MARK: - SIGN UP WITH FACEBOOK
// design the facebook button and assign #selector to facebook button actions
fileprivate func setUpFBButton() {
Utilities.styleHollowButton(signInFacebookButton)
signInFacebookButton.addTarget(self, action: #selector(handleCustomFBButton), for: .touchUpInside)
}
// handle the facebook button actions
#objc func handleCustomFBButton() {
LoginManager().logIn(permissions: ["email", "public_profile"], from: self) { (result, err) in
if err != nil {
print("Custom FB login failed:", err!)
return
}
self.getUserInfo()
}
}
// grab id, name, and email of user
func getUserInfo() {
print("Successfully logged in with facebook...")
GraphRequest(graphPath: "/me", parameters: ["fields": "id, name, email"]).start {
(connection, result, err) in
guard let Info = result as? [String: Any] else { return }
let name = Info["name"] as? String
let email = Info["email"] as? String
let uid = Info["id"] as? String
if err != nil {
print("Failed to start graph request:", err!)
return
}
print(result!)
self.signIntoFirebase(name ?? "", email ?? "", uid ?? "")
}
}
// connect the user to firebase
func signIntoFirebase(_ name:String, _ email:String, _ uid:String) {
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if let err = error {
print(err)
return
} else {
print("Facebook user successfully authenticated with Firebase. Now run through Firestore.")
// check if user already exists. if user exists, go to chats screen. if it does not exist, create a new user and redirect to chat screen.
self.addUserToFirestore(name, "", email, uid, "Facebook")
}
}
}
func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
print("Logged out of facebook")
}
// MARK: - Other functions
func addUserToFirestore(_ firstName:String, _ lastName:String, _ email:String, _ uid:String, _ signInMethod:String) {
let db = Firestore.firestore()
let docRef = db.collection("users").document(uid)
// check if user exists in firestore
docRef.getDocument { (document, error) in
if let document = document {
if document.exists {
let message = "Good news! You already have a Coal account that uses " + email + ".\nPlease sign in to your existing account. Then you will be able to link your " + signInMethod + " profile from your Account Settings page."
// user exists. send to chats screen.
print("User already exists. Document data: \(String(describing: document.data()))")
self.showError("You're already a member!", message)
} else {
// user does not exist. create a new user
print("Document does not exist. Create new user.")
docRef.setData(["firstname":firstName, "lastname":lastName, "email":email]) { err in
if err != nil {
// Show error message
print("Error saving user data to Firestore")
} else {
print("New user created in Firestore")
self.transitionToConvo()
}
}
}
}
}
}
func showError(_ title:String, _ message:String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
func transitionToConvo() {
let tabBarC = self.storyboard?.instantiateViewController(withIdentifier: "mainTabBarController") as! TabBarController
tabBarC.modalPresentationStyle = .fullScreen
self.present(tabBarC, animated: true, completion: nil)
print("Switched to TabBarController")
}
func setUpEmailButton() {
Utilities.styleDarkFilledButton(signInEmailButton)
}
} // end
I think the reason why it's not getting an alert is because the Facebook uid doesn't match the email uid saved in Firestore (while Google uid does match). The way I'm getting the alert to show up is if the uid matches that in Firestore, so consequently, the alert doesn't show. Does anyone know how I can get the alert to show an how to not get this error?
I know my code is a bit messy, so please let me know if you need further explanation. Any help is appreciated!!
After hours of trying to figure out my problem, I decided to post a question... but almost immediately after, found the answer (i know right :/).
Since one account per email is already enabled in the project settings, Auth.auth().signIn automatically scans if a user exists. If a user exists, it'll return an error after if error != nil. Because it returned an error before my addUserToFirestore function was called (to check if the user exists and if not, add user to Firestore), the alert was never shown.
Now that we know what if error != nil means, we can just insert the alert there:
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
let message = "Good news! You already have a Coal account that uses " + email + ".\nPlease sign in to your existing account. Then you will be able to link your Facebook profile from your Account Settings page."
// user exists. send to chats screen.
print("User already exists. Let user know.")
self.showError("You're already a member!", message)
return
}
I'm not sure why it worked for Google Auth, but it ended up that this is what worked for Facebook Auth.

Retrieving user email, using FBSDKLoginKit, from an account registered with phone number only: what does "email" result returns?

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)
})
}
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) -> Void 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)
}
})
}
}

Swift / Firebase: How do I properly store a Facebook user into Firebase database when they create an account?

I'm trying to save users to my firebase database. I'm using a FBSDKLoginManager() to create an account / log in. Upon account creation, I want to store the users into my firebase database. I can currently log the user in and their email shows up in the Auth tab of firebase (see screenshot), but my updateChildValues doesn't seem to be having any affect (also see screenshot).
Am I placing the updateChildValues in the right place? It's currently place within signInWithCredential. I also have to perform an FBSDKGraphRequest to get the info I'm interested in storing in my firebase database.
The Auth tab of my firebase shows the authentication is working:
But the Database isn't being updated:
func showLoginView() {
let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(fbPermissions, fromViewController: self, handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if ((error) != nil) {
print("Error loggin in is \(error)")
} else if (result.isCancelled) {
print("The user cancelled loggin in")
} else {
// No error, No cancelling:
// using the FBAccessToken, we get a Firebase token
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
// using the credentials above, sign in to firebase to create a user session
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
print("User logged in the firebase")
// adding a reference to our firebase database
let ref = FIRDatabase.database().referenceFromURL("https://project-12345.firebaseio.com/")
// guard for user id
guard let uid = user?.uid else {
return
}
// create a child reference - uid will let us wrap each users data in a unique user id for later reference
let usersReference = ref.child("users").child(uid)
// performing the Facebook graph request to get the user data that just logged in so we can assign this stuff to our Firebase database:
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil) {
// Process error
print("Error: \(error)")
} else {
print("fetched user: \(result)")
// Facebook users name:
let userName:NSString = result.valueForKey("name") as! NSString
self.usersName = userName
print("User Name is: \(userName)")
print("self.usersName is \(self.usersName)")
// Facebook users email:
let userEmail:NSString = result.valueForKey("email") as! NSString
self.usersEmail = userEmail
print("User Email is: \(userEmail)")
print("self.usersEmail is \(self.usersEmail)")
// Facebook users ID:
let userID:NSString = result.valueForKey("id") as! NSString
self.usersFacebookID = userID
print("Users Facebook ID is: \(userID)")
print("self.usersFacebookID is \(self.usersFacebookID)")
}
})
// set values for assignment in our Firebase database
let values = ["name": self.usersName, "email": self.usersEmail, "facebookID": self.usersFacebookID]
// update our databse by using the child database reference above called usersReference
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
// if there's an error in saving to our firebase database
if err != nil {
print(err)
return
}
// no error, so it means we've saved the user into our firebase database successfully
print("Save the user successfully into Firebase database")
})
}
}
})
}
Update:
Apparently after 10 minutes or so, the database was updated with empty Facebook data... Not sure why it's taking so long. Here's a screenshot:
Swift 3: (only changed it at the end, saves a lot of lines)
func showLoginView() {
let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(fbPermissions, fromViewController: self, handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if ((error) != nil) {
print("Error loggin in is \(error)")
} else if (result.isCancelled) {
print("The user cancelled loggin in")
} else {
// No error, No cancelling:
// using the FBAccessToken, we get a Firebase token
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
// using the credentials above, sign in to firebase to create a user session
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
print("User logged in the firebase")
// adding a reference to our firebase database
let ref = FIRDatabase.database().referenceFromURL("https://project-12345.firebaseio.com/")
// guard for user id
guard let uid = user?.uid else {
return
}
// create a child reference - uid will let us wrap each users data in a unique user id for later reference
let usersReference = ref.child("users").child(uid)
// performing the Facebook graph request to get the user data that just logged in so we can assign this stuff to our Firebase database:
let graphRequest : FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "id, email, name"]).start{
(connection, result, err) in
if ((error) != nil) {
// Process error
print("Error: \(error)")
} else {
print("fetched user: \(result)")
let values: [String:AnyObject] = result as! [String : AnyObject]
// update our databse by using the child database reference above called usersReference
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
// if there's an error in saving to our firebase database
if err != nil {
print(err)
return
}
// no error, so it means we've saved the user into our firebase database successfully
print("Save the user successfully into Firebase database")
})
}
})
}
}
})
}
You should only update the values when the completion block graphRequest.startWithCompletionHandler is executed because that's when you will get your data from the Facebook!.
usersReference.updateChildValues needs to be inside graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in the completion block. I have attached it below. Try it!!
func showLoginView() {
let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(fbPermissions, fromViewController: self, handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if ((error) != nil) {
print("Error loggin in is \(error)")
} else if (result.isCancelled) {
print("The user cancelled loggin in")
} else {
// No error, No cancelling:
// using the FBAccessToken, we get a Firebase token
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
// using the credentials above, sign in to firebase to create a user session
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
print("User logged in the firebase")
// adding a reference to our firebase database
let ref = FIRDatabase.database().referenceFromURL("https://project-12345.firebaseio.com/")
// guard for user id
guard let uid = user?.uid else {
return
}
// create a child reference - uid will let us wrap each users data in a unique user id for later reference
let usersReference = ref.child("users").child(uid)
// performing the Facebook graph request to get the user data that just logged in so we can assign this stuff to our Firebase database:
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil) {
// Process error
print("Error: \(error)")
} else {
print("fetched user: \(result)")
// Facebook users name:
let userName:NSString = result.valueForKey("name") as! NSString
self.usersName = userName
print("User Name is: \(userName)")
print("self.usersName is \(self.usersName)")
// Facebook users email:
let userEmail:NSString = result.valueForKey("email") as! NSString
self.usersEmail = userEmail
print("User Email is: \(userEmail)")
print("self.usersEmail is \(self.usersEmail)")
// Facebook users ID:
let userID:NSString = result.valueForKey("id") as! NSString
self.usersFacebookID = userID
print("Users Facebook ID is: \(userID)")
print("self.usersFacebookID is \(self.usersFacebookID)")
//graphRequest.startWithCompletionHandler may not come back during serial
//execution so you cannot assume that you will have date by the time it gets
//to the let values = ["name":
//By putting it inside here it makes sure to update the date once it is
//returned from the completionHandler
// set values for assignment in our Firebase database
let values = ["name": self.usersName, "email": self.usersEmail, "facebookID": self.usersFacebookID]
// update our databse by using the child database reference above called usersReference
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
// if there's an error in saving to our firebase database
if err != nil {
print(err)
return
}
// no error, so it means we've saved the user into our firebase database successfully
print("Save the user successfully into Firebase database")
})
}
})
}
}
})
}

Retrieve email FacebookSDK and Swift

I'm successfully implemented facebook login in my app, but I'm not able to query/retrieve the email address from the user.
I have the following code:
import UIKit
class testViewController: UIViewController, FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// User is already logged in, do work such as go to next view controller.
// Or Show Logout Button
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
self.returnUserData()
}
else
{
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
}
// Facebook Delegate Methods
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
println("User Logged In")
if ((error) != nil)
{
// Process error
}
else if result.isCancelled {
// Handle cancellations
}
else {
// If you ask for multiple permissions at once, you
// should check if specific permissions missing
if result.grantedPermissions.contains("email")
{
// Do work
}
self.returnUserData()
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
println("User Logged Out")
}
func returnUserData() {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println("fetched user: \(result)")
let userName : NSString = result.valueForKey("name") as! NSString
println("User Name is: \(userName)")
let userEmail : NSString = result.valueForKey("email") as! NSString
println("User Email is: \(userEmail)")
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And the println output:
fetched user: {
id = 808101565906152;
name = "Marcelo Pontes Machado";
}
When I try to display the email I got a nill value.
I think the code is right, maybe some SDK that I miss to import?
Put the fields you want back from the Graph request in your parameters
FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id,email,name,picture.width(480).height(480)"]).startWithCompletionHandler({
Because the Graph API may sometimes only return a minimum amount of information unless otherwise requested.
In Swift
if((FBSDKAccessToken.current()) != nil)
{
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(completionHandler:
{ (connection, result, error) -> Void in
if (error == nil)
{
//everything works print the user data
// print(result!)
if let data = result as? NSDictionary
{
let firstName = data.object(forKey: "first_name") as? String
let lastName = data.object(forKey: "last_name") as? String
if let email = data.object(forKey: "email") as? String
{
print(email)
}
else
{
// If user have signup with mobile number you are not able to get their email address
print("We are unable to access Facebook account details, please use other sign in methods.")
}
}
}
})
}
In Objective C wire this code
// START_LOADING;
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me"
parameters:#{#"fields": #"picture, email,first_name,last_name"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
{
if (!error)
{
if ([result valueForKey:#"email"] != nil)
{
NSLog([result valueForKey:#"email"]);
}
else
{
// If user have signup with mobile number you are not able to get their email address
NSLog(#"We are unable to access Facebook account details, please use other sign in methods.");
// STOP_LOADING;
}
}
}];

Get Facebook user details with swift and parse

i need to get the Facebook user information details when i login a new user through parse. at present i am logging in the new user below. can't seem to get the user details though. I've seen some code written on objective - c. most of the functions don't work anymore
The Facebook iOS sdks i am running is v4.3.0.
#IBAction func facebookButton(sender: AnyObject) {
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions) {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
println("User signed up and logged in through Facebook!")
} else {
println("User logged in through Facebook!")
}
} else {
println("Uh oh. The user cancelled the Facebook login.")
}
}
}
To get the user details you have to send a FBSDKGraphRequest after the login request.
This can be done inside the if let user = user {...} block.
// Create request for user's Facebook data
let request = FBSDKGraphRequest(graphPath:"me", parameters:nil)
// Send request to Facebook
request.startWithCompletionHandler {
(connection, result, error) in
if error != nil {
// Some error checking here
}
else if let userData = result as? [String:AnyObject] {
// Access user data
let username = userData["name"] as? String
// ....
}
}
For the new Facebook API and version of Swift 3.1 you can do something like this:
if((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id,name,first_name,last_name,email"]).start(completionHandler: {(connection, result, error) -> Void in
if(error != nil) {
print("Some error occurred.");
} else {
print(result!)
}
})
}