Parse and Facebook Login creating an empty user - ios

now that Parse belongs to Facebook's family I hope you can help me to find a quick solution to my problem.
My app crashes sometimes when a user logs in for the first time thru Facebook, the reason of this crash is that for some reason (and I say it again) SOMETIMES this user is created empty on parse's data base, it only gets an Auth Data, and every other field is empty, so when I get the parseUser its completely empty and everything crashes. I know I could validate everything so it won't crash, but my question is WHY IS THIS HAPPENING? AND WHY IT DOESN'T HAPPENS ALWAYS? I am requesting al permissions and all the info that I need from the user in my code.
This is the whole method that I am using: I really hope someone can help me:
func fbLogin (successBlock:(result:User) -> () , errorBlock: (error:String) -> ()) {
PFFacebookUtils.logInInBackgroundWithReadPermissions(kFbPermissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
println("User signed up and logged in through Facebook!")
FBSDKGraphRequest(graphPath: "me", parameters: nil).startWithCompletionHandler({ (connection, result, error) -> Void in
var loggedUser = User(result: result,aParseObject: user)
loggedUser.saveUser()
appDelegate.loggedUser = loggedUser
successBlock (result: loggedUser
})
})
} else {
println("User logged in through Facebook!")
var loggedUser = User(aParseObject: user)
appDelegate.loggedUser = loggedUser
println (appDelegate.loggedUser!.objectId)
successBlock(result: loggedUser)
}
} else {
println("Uh oh. The user cancelled the Facebook login.")
errorBlock (error: localizedStringForKey("loginCanceled"))
}
})
}

Related

Unable to get Facebook permissions after HTTPMethod DELETE in Swift

I am working on an app that logs in to Facebook using the FBSDK in Swift. I also have been able to make requests to get my wall posts by using
var request: FBSDKGraphRequest
request = FBSDKGraphRequest(graphPath: "me/feed"), parameters: ["access_token": FBSDKAccessToken.currentAccessToken().tokenString], HTTPMethod:"GET")
request.startWithCompletionHandler({(connection, result, error) -> Void in
if error != nil
{
}
else
{
}
})
but I have been unable to get back results after I used the following to log out
var deletePermission = FBSDKGraphRequest(graphPath: "me/permissions/", parameters: nil, HTTPMethod: "DELETE")
deleterPermission.startWithCompletionHandler({(connection, result, error) -> Void in
if error != nil
{
}
else
{
}
})
When I log back in to the app, I am again asked to accept permissions, but when I check the expiration date for the current token with FBSDKAccessToken.currentAccessToken().expirationDate I get a date before I tried HTTPMethod: DELETE.
So I was wondering how it would be possible to get back permission for your app or renew my access token because I don't think it's working by logging back in and accepting permissions. I have used the following to log out of the app
// Log out of the database I'm using
try! FIRAuth.auth()!.signOut()
// Log out of Facebook, clear current token and logged user
FBSDKAccessToken.setCurrentAccessToken(nil)
FBSDKProfile.setCurrentProfile(nil)
I am also using `FBSDKLoginButton()' and setting the following permissions to log in
var loginButton = FBSDKLoginButton()
loginButton.readPermissions = ["public_profile", "user_friends", "user_about_me", "user_posts"]
loginButton.delegate = self
....
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if error == nil
{
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken().tokenString)
// Firebase authentication
FIRAuth.auth()?.signInWithCredential(credential) {(user, error) in
if error == nil
{
// No error found get user credentials through Firebase
}
else
{
}
}}
But again after logging in and going to another ViewController by segue and I check the current token to get "me/feed" I am not getting a reply and the token's expiration date has expired. Would it be easier to create a new app in Facebook developer and set it up in Xcode or is there something I can do to get my user posts?

Handle Invalidated Token Alert from Facebook SDK

P.S: Please help me vote up this question since it is really really
difficult to find the solution.
Below is my code to check if my facebook token is valid or not.
var request: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil);
request.startWithCompletionHandler { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if error == nil {
println("No Error")
}
else {
PFFacebookUtils.unlinkUserInBackground(SLUser.currentUser()!);
println("Error")
}
}
What is weird is that, IF the token is not valid (user has changed password or user has revoked the application permission) the app automatically shows an Alert like below.
My question is:
How do I handle when user press OK or Cancel?
Is it possible to disable that Alert or Replace it?

Parse + Facebook Questions

I am trying to implement Parse + Facebook
Here is what I would like to do:
User Log In with Facebook
Login Authorized
A new User created from Facebook properties (gender, age, name, etc)
Below is my code which logs in to Facebook using PFFacebookUtils. The code successfully created a User on my Parse, but I don't have those details of the User from Facebook which I want to use.
I would like to get the user's name, gender, hometown, etc on Facebook.
How do I achieve that??
var permissionArray = ["public_profile","user_friends","email","user_birthday", "user_work_history", "user_education_history", "user_hometown", "user_location", "user_likes"]; on Facebook
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissionArray) { (user: PFUser?, error: NSError?) -> Void in
if user != nil {
if user!.isNew {
println("New User");
}
else {
println("Old User");
}
println(user?.username);
}
else {
println("Login Cancel")
}
}
You need to request the users "me" data, and then you can use that to populate your user object. So, in your if user!.isNew { you'll need to do something along the lines of...
let fbDetailsRequest = FBRequest.requestForMe()
fbDetailsRequest.startWithCompletionHandler { connection, result, error in
if error != nil {
// Handle the error
}
if let graph = result as? FBGraphObject {
// Now you can fill out the data on your user object
user!.setObject(graph.objectForKey("email")!, forKey: "email")
user!.setObject(graph.objectForKey("gender")!, forKey: "gender")
// Don't forget to save afterwards...
user!.saveInBackgroundWithBlock(nil)
}
}
To see the fields you can grab, check out https://developers.facebook.com/docs/graph-api/reference/user If you need anything other than "core" items, you might have to have extra permissions.

XCode - Swift - Facebook Authentication with Parse

I have Facebook authentication integrated with parse using the following code:
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions) {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler { (connection, result, error) -> Void in
user["email"] = result.valueForKey("email") as! String
user["firstName"] = result.valueForKey("first_name") as! String
user["lastName"] = result.valueForKey("last_name") as! String
user.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
// goto app
}
}
} else {
// goto app
}
} else {
// Canceled
}
}
So I use Parse's PFFacebookUtils to login the user, then add the extra fields email, firstName and lastName based on the user's Facebook info, then I log the user in. Just wondering if this is the right way to go about adding those additionals fields, and I was also wondering if there was a way to stop an email confirmation from going out in this scenario? I have a register via email option so I need email confirmation, but just not for Facebook login.
Yes as far as I know that is the correct way to set new field. Maybe you want to check for nil in the optionals instead of explicitly unwrapping like that?
And no I think every time you set the email on a PFUser it will send the authentication email if you have that option on in Parse.
One option to save the email without notifying them is to create your own emailId field and set it to that so that they don't get an email asking for authentication and when signing up a new user with email you can also set that field to be the same emailId (it is kind of messy cause you have the same value repeated) but its a workaround worth trying.

Using Swift, Parse and the iOS FacebookSDK, how do I obtain user's name and email at login?

So I've been banging my head on this for a couple days now, and I'm hoping someone here could shed some light on this for me!
So I'm using Parse in my Swift project, and am looking to leverage the Facebook integration to make logging in and signing up a user pretty effortless.
I have managed to get as far as logging in a user, but the part where I'm stuck is that I don't know how to access the data that I requested with permissions.
In my AppDelegate Swift file, I have this block of code..
// INITIALISE FACEBOOK
let permissions = ["email", "public_profile"]
PFFacebookUtils.initializeFacebook()
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
if (error == nil) {
println("User cancelled Facebook login")
} else {
println("FB Login Error \n(error)")
}
} else if user.isNew {
println("User has signed in through Facebook!")
} else {
println("User logged in through Facebook!")
}
})
Everything is all well and dandy, and I get the "User has signed in through Facebook!" message.
According to the Parse documentation, this then creates a new User object in my database.
In my database, I see that there is indeed a new user, but the only fields that are populated are..
ObjectID - random string characters
username - random string characters
authData - a facebook type ID.
Not the username or email.
From what I have gathered, I need to now further leverage the FacebookSDK and GraphUser, but I really dont know exactly how.. or at least not in Swift.
The Parse documentation says
"The Facebook iOS SDK provides a number of helper classes for interacting with Facebook's API. Generally, you will use the FBRequest class to interact with Facebook on behalf of your logged-in user. You can read more about the Facebook SDK here.
Our library manages the user's FBSession object for you. You can simply call [PFFacebookUtils session] to access the session instance, which can then be passed to FBRequests."
But I really dont know what to type or where to type it. :(
It feels like I'm really close with this, but I'm just hitting blanks..
If someone could be kind enough to shed some light into this (how to access the details I requested permission for, i.e. full name and email) I would be incredibly grateful!
Thank you.. :)
You may try this (for Swift):
// Obtain User Data via Facebook Login
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"name, email"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
}
else
{
let userName: String = result.valueForKey("name") as! String
let Email: String = result.valueForKey("email") as! String
println(userName)
println(Email)
}
})
}
According to this: https://parse.com/questions/how-can-i-get-the-facebook-id-of-a-user-logged-in-with-facebook
You get the Facebook ID with this Objective-C
// After logging in with Facebook
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSString *facebookId = [result objectForKey:#"id"];
}
}];
Which is this in Swift (not tested)
FBRequestConnection.startForMeWithCompletionHandler { connection, result, error in
if (!error) {
let facebookId = result["id"]
// use facebookID
}
}

Resources