I'm creating an application with Parse as backend service. My users should be able to sign-up and login via Facebook.
I did this in the following (works absolutely fine).
#IBAction func registerWithFacebook(sender: UIButton) {
let permissions:[String] = ["user_about_me","user_relationships", "public_profile"]
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
self.loadData()
self.performSegueWithIdentifier("initialToMain", sender: self)
} else {
NSLog("User logged in through Facebook!")
self.performSegueWithIdentifier("initialToMain", sender: self)
}
})
}
func loadData(){
let request:FBRequest = FBRequest.requestForMe()
request.startWithCompletionHandler { (connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if error == nil{
if let dict = result as? Dictionary<String, AnyObject>{
let name:String = dict["name"] as AnyObject? as String
let email:String = dict["email"] as AnyObject? as String
println(name)
PFUser.currentUser().setValue(name, forKey: "username")
PFUser.currentUser().setValue(email, forKey: "email")
PFUser.currentUser().save()
}
}
}
}
Unfortunately I wasn't able to get the profile picture from the user who's signing up. How can I do that?
The picture is publicly available via the user id at the following url:
https://graph.facebook.com/USER_ID/picture
You can also request various sizes:
https://graph.facebook.com/USER_ID/picture?width=300&height=300
Here's the working solution:
func loadData(){
let request:FBRequest = FBRequest.requestForMe()
request.startWithCompletionHandler { (connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if error == nil{
if let dict = result as? Dictionary<String, AnyObject>{
let name:String = dict["name"] as AnyObject? as String
let facebookID:String = dict["id"] as AnyObject? as String
let email:String = dict["email"] as AnyObject? as String
let pictureURL = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
var URLRequest = NSURL(string: pictureURL)
var URLRequestNeeded = NSURLRequest(URL: URLRequest!)
NSURLConnection.sendAsynchronousRequest(URLRequestNeeded, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!, error: NSError!) -> Void in
if error == nil {
var picture = PFFile(data: data)
PFUser.currentUser().setObject(picture, forKey: "profilePicture")
PFUser.currentUser().saveInBackground()
}
else {
println("Error: \(error.localizedDescription)")
}
})
PFUser.currentUser().setValue(name, forKey: "username")
PFUser.currentUser().setValue(email, forKey: "email")
PFUser.currentUser().saveInBackground()
}
}
}
}
Related
I have issues with loading user photo from facebook.
I want to fetch facebook user photo to parse data base.
My code:
let permissions:[String] = ["public_profile", "email"]
PFFacebookUtils.logInInBackground(withReadPermissions: permissions) { (user, error) in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user!.isNew {
NSLog("User signed up and logged in through Facebook!")
self.loadData()
} else {
NSLog("User logged in through Facebook!")
}
}
func loadData(){
let fbRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
fbRequest?.start(completionHandler: { (FBSDKGraphRequestConnection, result, error) in
if error == nil{
if let dict = result as? Dictionary<String, AnyObject>{
let name:String = dict["name"] as AnyObject? as! String
let facebookID:String = dict["id"] as AnyObject? as! String
let email:String = dict["email"] as AnyObject? as! String
let pictureURL = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
let URLRequest = NSURL(string: pictureURL)
let URLRequestNeeded = NSURLRequest(url: URLRequest! as URL)
NSURLConnection.sendAsynchronousRequest(URLRequestNeeded as URLRequest, queue: OperationQueue.main, completionHandler: { (response, data, error) in
if error == nil {
let picture = PFFile(data: data!)
PFUser.current()?.setObject(picture!, forKey: "profilePicture")
PFUser.current()?.saveInBackground()
}
else {
print("Error: \(String(describing: error?.localizedDescription))")
}
})
PFUser.current()!.setValue(name, forKey: "username")
PFUser.current()!.setValue(email, forKey: "email")
PFUser.current()!.saveInBackground()
}
}
})
}
But i all time i have error message, and in data base i have empty row.
How i can fix it?
After trying many methods, this is what works for me.
On AppDelegate, import Parse, ParseFacebookUtilsV4 and FBSDKCoreKit
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
PFFacebookUtils.initializeFacebook(applicationLaunchOptions: launchOptions)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
and add two methods
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
app,
open: url as URL?,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplication.OpenURLOptionsKey.annotation]
)
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
application,
open: url as URL?,
sourceApplication: sourceApplication,
annotation: annotation)
}
And then, on login ViewController:
#IBAction func signInFacebook(_ sender: Any)
{
let permissions = ["public_profile", "email"]
PFFacebookUtils.logInInBackground(withReadPermissions: permissions) { (user : PFUser?, error: Error?) in
if(error != nil)
{
//Display an alert message
let myAlert = UIAlertController(title:"Alert", message:error?.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil)
myAlert.addAction(okAction)
self.present(myAlert, animated:true, completion:nil);
return
}
else
{
let query = PFQuery(className: "_User")
query.whereKey("email", equalTo: NSNull())
query.findObjectsInBackground (block: { (objects, error) -> Void in
if error == nil
{
// found related objects
for object in objects! {
//delete error user
print(object.value(forKey: "username")!)
object.deleteEventually()
}
}
else{
print(error!.localizedDescription)
}
}
)}
self.indicator.isHidden = false
self.indicator.startAnimating()
self.setUp.isHidden = false
if(FBSDKAccessToken.current() != nil) {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email, first_name, last_name"]).start(completionHandler: { (connection, result, error) in
let resultDic = result as! [String: Any]
let nameFB = resultDic["name"] as! String
let emailFB = resultDic["email"] as! String
let idFB = resultDic["id"] as! String
let firstFB = resultDic["first_name"] as! String
let lastFB = resultDic["last_name"] as! String
// correct in case of double First or Last name
let firstFBNoSpaces = firstFB.replacingOccurrences(of: " ", with: "_", options: .literal, range: nil)
let lastFBNoSpaces = lastFB.replacingOccurrences(of: " ", with: "_", options: .literal, range: nil)
var userNameNew = firstFBNoSpaces + "_" + lastFBNoSpaces
userNameNew = userNameNew.lowercased()
// send data to server to related columns
let user = PFUser()
user.username = userNameNew.lowercased()
user.email = emailFB.lowercased()
user.password = idFB
user["fullname"] = nameFB.capitalized
UserDefaults.standard.set(user.username, forKey: "username")
// get Facebook profile picture
let userProfile = "https://graph.facebook.com/" + idFB + "/picture?type=large"
let profilePictureUrl = NSURL(string: userProfile)
let profilePictureData = NSData(contentsOf: profilePictureUrl! as URL)
if(profilePictureData != nil)
{
let avaFile = PFFile(data:profilePictureData! as Data)
user["ava"] = avaFile
}
// will try to login with facebook
user.signUpInBackground { (success, error) -> Void in
if success
{
// remember looged user
UserDefaults.standard.set(user.username, forKey: "username")
UserDefaults.standard.set(true, forKey: "byFacebook")
// call login func from AppDelegate.swift class
let appDelegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.login()
self.setUp.isHidden = true
self.indicator.isHidden = true
self.indicator.stopAnimating()
}
else
{
let existing : String? = UserDefaults.standard.string(forKey: "username")
// user already exists in app database
PFUser.logInWithUsername(inBackground: existing!, password: user.password!){ (user, error) -> Void in
if error == nil
{
// remember user or save in App Memory did the user login or not
UserDefaults.standard.set(user!.username, forKey: "username")
UserDefaults.standard.set(true, forKey: "byFacebook")
// call login function from AppDelegate.swift class
let appDelegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.login()
self.setUp.isHidden = true
self.indicator.isHidden = true
self.indicator.stopAnimating()
}
}
}
}
})
}
else
{
self.setUp.isHidden = true
self.indicator.isHidden = true
self.indicator.stopAnimating()
}
}
}
you can try
#IBAction func loginFacebookAction(sender: AnyObject) {//action of the custom button in the storyboard
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["email"], from: self) { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result!
// if user cancel the login
if (result?.isCancelled)!{
return
}
if(fbloginresult.grantedPermissions.contains("email"))
{
self.getFBUserData()
}
}else {
print(error!.localizedDescription)
// self.view.showToast(withMessage: error!.localizedDescription)
}
}
}
func getFBUserData(){
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? [String:Any],
// let user = Mapper<User>().map(
// JSONObject: data
// ){
// AppHelper.set(currentuser: user)
// }
}else {
// self.view.showToast(withMessage: error!.localizedDescription)
print(error!.localizedDescription)
}
})
}
}
I got my app onto the App Store. Everything was working fine on my end, and apparently on the reviewers end.
After the app went live, some users reported crashing immediately after they log in with Facebook. Here's the code for where I think it's crashing (run right after users log in with Facebook):
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
protocol getUserDataDelegate {
func gotData()
}
public var userEmailForMixpanel = ""
public var userNameForInvites = ""
class GetUserData: NSObject {
var facebookid:String = ""
var userEmail:String = ""
var userFirstName:String = ""
var userLastName: String = ""
var userGender:String = ""
var userBirthday:String = ""
var delegate = getUserDataDelegate?()
func returnUserData() {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, email, first_name, last_name, gender, birthday"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
print("Error: \(error)")
}
else
{
self.facebookid = (result.valueForKey("id") as? String)!
self.userEmail = (result.valueForKey("email") as? String)!
self.userFirstName = (result.valueForKey("first_name") as? String)!
self.userLastName = (result.valueForKey("last_name") as? String)!
self.userGender = (result.valueForKey("gender") as? String)!
//self.userBirthday = (result.valueForKey("birthday") as? String)!
userEmailForMixpanel = self.userEmail
userNameForInvites = self.userFirstName
NSUserDefaults.standardUserDefaults().setValue(userEmailForMixpanel, forKey: "userEmail")
NSUserDefaults.standardUserDefaults().setValue(userNameForInvites, forKey: "userName")
NSUserDefaults.standardUserDefaults().synchronize()
Mixpanel.sharedInstanceWithToken("abdc")
let mixpanel = Mixpanel.sharedInstance()
mixpanel.registerSuperProperties(["Gender":self.userGender])
print(self.facebookid)
print(self.userEmail)
print(self.userFirstName)
print(self.userLastName)
print(self.userGender)
//print(self.userBirthday)
self.checkIfUserExists()
}
})
}
func checkIfUserExists() {
showTutorial = true
let url:NSURL = NSURL(string: "url")!
let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
let userTokenDataDictionary:NSDictionary = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
if userTokenDataDictionary ["token"] != nil {
userAccessToken = (userTokenDataDictionary["token"] as? String)!
NSUserDefaults.standardUserDefaults().setValue(userAccessToken, forKey: "userAccessToken")
NSUserDefaults.standardUserDefaults().synchronize()
print("Token for Existing User:\(userAccessToken)")
self.finishedGettingData()
}
if userTokenDataDictionary ["error"] != nil {
userAccessToken = (userTokenDataDictionary["error"] as? String)!
print(userAccessToken)
print("User needs to be created")
self.createNewUserFromFacebook()
}
}
task.resume()
}
func createNewUserFromFacebook() {
let url:NSURL = NSURL(string: "url")!
print(url)
let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
let userTokenDataDictionary:NSDictionary = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
if userTokenDataDictionary ["token"] != nil {
userAccessToken = (userTokenDataDictionary["token"] as? String)!
NSUserDefaults.standardUserDefaults().setValue(userAccessToken, forKey: "userAccessToken")
NSUserDefaults.standardUserDefaults().synchronize()
}
if userTokenDataDictionary ["error"] != nil {
userAccessToken = (userTokenDataDictionary["error"] as? String)!
print(userAccessToken)
}
print("Token for New User:\(userAccessToken)")
self.finishedGettingData()
}
task.resume()
}
func checkIfUserHasUsedListenerApp() {
let accessToken = NSUserDefaults.standardUserDefaults().stringForKey("userAccessToken")!
let url:NSURL = NSURL(string: "url")!
print(url)
let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
let adDataDict:NSDictionary = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
if adDataDict ["used_ListenerApp"] != nil {
let responseCode = adDataDict.valueForKey("used_ListenerApp") as! Bool
print(responseCode)
if responseCode == false {
Mixpanel.sharedInstanceWithToken("abc")
let mixpanel = Mixpanel.sharedInstance()
mixpanel.track("New User Signed Up", properties: ["distinct_id":userEmailForMixpanel])
}
if responseCode == true {
return
}
}
}
task.resume()
}
func finishedGettingData() {
self.checkIfUserHasUsedListenerApp()
Mixpanel.sharedInstanceWithToken("abc")
let mixpanel = Mixpanel.sharedInstance()
mixpanel.track("User Logged In", properties: ["distinct_id":userEmailForMixpanel])
if let actualdelegate = self.delegate {
actualdelegate.gotData()
}
}
}
It's only crashing for some users, not all. I even tried creating a loop that generates a bunch of user data to run it through this code, and I couldn't replicate the crash.
Any advice would be appreciated a lot.
UPDATE
It looks like it has to do with Facebook not returning an email address. I'll keep looking though.
I figured it out. Part of the problem was that Facebook wasn't returning an email address for some users, so I checked for that and if it didn't return an email, I created one with their Facebook ID to get them through the login process (fbid#facebook.mywebsite.com).
Another part of the problem was that some users had logged into my website using an email address that was also assigned to their Facebook account, and tried logging in with Facebook on the app. I fixed this by having it merge their Facebook info with their existing account during the authorization process if an existing account is found.
Can't get the user's name or email when login with Facebook via Parse. I should have set everything else properly in the AppDelegate.
When I login with my email, my User class works, and can use data I registered with. When I try to login via Facebook, I only got the long alphanumerical string as username and stop. I'd like to retrive name, foto, birth and city.
In my User.swift file I'got this:
import Foundation
struct User
{
let username : String
let address : String
}
This is my login button:
#IBAction func facebookLoginAction(sender: UIButton)
{
PFFacebookUtils.logInInBackgroundWithReadPermissions(["public_profile", "user_about_me", "user_birthday"]) {
(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!")
}
self.dismissViewControllerAnimated(true, completion: nil)
}
else
{
println("Uh oh. The user cancelled the Facebook login.")
}
}
}
tried this too, but doesn't work:
func getUserInfo() {
// if let session = PFFacebookUtils.session() {
if let session = PFFacebookUtils.facebookLoginManager() {
if session.isOpen {
println("session is open")
FBRequestConnection.startForMeWithCompletionHandler({ (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
//println("done me request")
if error != nil {
println("facebook me request - error is not nil :(")
} else {
println("facebook me request - error is nil :) ")
let urlUserImg = "http://graph.facebook.com/\(result.objectID)/picture?type=large"
let firstName = result.first_name
let lastName = result.last_name
}
})
}
} else {
//let user:PFUser = PFUser.currentUser()
//println("ohooo \(user)")
}
}
thanks in advance
This is working code I use to get Facebook information with Parse. The function is called after successful authentication with user.isNew. It can also be called even if the user isn't new to make sure you have the most up-to-date information when they log back in.
func loadFacebookData() {
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "email, name, id"])
graphRequest.startWithCompletionHandler { (connection, result, error) -> Void in
if error != nil {
let error = error!.userInfo["error"] as! String
}
else {
if let userName = result.valueForKey("name") as? String, email = result.valueForKey("email") as? String, id = result.valueForKey("id") as? String {
let pictureURL: NSURL = NSURL(string: "https://graph.facebook.com/\(id)/picture?type=large&return_ssl_resources=1")!
let user = PFUser.currentUser()!
let query = PFUser.query()
query!.whereKey("email", equalTo: email)
query!.getFirstObjectInBackgroundWithBlock({ (oldUser: PFObject?, error) -> Void in
if error != nil && oldUser != nil {
let error = error!.userInfo["error"] as! String
}
else {
self.setFacebookInfo(user, userEmail: email, userName: userName, pictureURL: pictureURL)
}
})
}
}
}
}
I've linked my app to both the Facebook SDK and Parse, but now I'm trying to integrate Facebook's login with Parse but keep running into issues. My current issue is that the app runs, but when I press the FBSDKLoginButton, it will go to safari and ask for permissions (as it should), but then when pressing okay, it simply returns to the app's login screen like nothing happened and does not perform the segue to the rest of the app. I also checked Parse and it did not create a new PFUser. I will post the code I think may be relevant from my LoginViewController below (that means the code will be missing sections like my viewDidLoad for it has nothing in it that affects the login process):
import UIKit
import Parse
import FBSDKCoreKit
import FBSDKLoginKit
protocol LoginViewControllerDelegate {
func onRegister(loginViewController : LoginViewController)
func onFacebookLogin(loginViewController : LoginViewController)
func onLogin(loginViewController : LoginViewController)
}
class LoginViewController: UIViewController {
#IBAction func onFacebookLogin(sender: AnyObject?) {
// Set permissions required from the facebook user account
let permissions = [ "user_about_me", "user_relationships", "user_location", "user_birthday", "public_profile", "user_friends", "user_email", "user_gender"]
// Login PFUser using Facebook
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
println("User signed up and logged in through Facebook!")
self.loadData()
self.performSegueWithIdentifier("loggedIn", sender: self)
} else {
println("User logged in through Facebook!")
self.performSegueWithIdentifier("loggedIn", sender: self)
}
if self.delegate != nil {
self.delegate!.onFacebookLogin(self)
}
} else {
println("Uh oh. The user cancelled the Facebook login.")
}
})
}
func loadData(){
let request:FBSDKGraphRequest = FBSDKGraphRequest()
request.startWithCompletionHandler { (connection:FBSDKGraphRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if error == nil{
if let dict = result as? Dictionary<String, AnyObject>{
let name:String = dict["first_name"] as AnyObject? as! String
let facebookID:String = dict["id"] as AnyObject? as! String
let email:String = dict["email"] as AnyObject? as! String
let birthday:String = dict["birthday"] as AnyObject? as! String
let gender:String = dict["gender"] as AnyObject? as! String
let hostCount:Int = 0
let attendCount:Int = 0
let pictureURL = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
var URLRequest = NSURL(string: pictureURL)
var URLRequestNeeded = NSURLRequest(URL: URLRequest!)
NSURLConnection.sendAsynchronousRequest(URLRequestNeeded, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!, error: NSError!) -> Void in
if error == nil {
var picture = PFFile(data: data)
PFUser.currentUser()!.setObject(picture, forKey: "profilePicture")
PFUser.currentUser()!.saveInBackground()
}
else {
println("Error: \(error.localizedDescription)")
}
})
PFUser.currentUser()!.setValue(name, forKey: "name")
PFUser.currentUser()!.setValue(email, forKey: "email")
PFUser.currentUser()!.setValue(birthday, forKey: "birthday")
PFUser.currentUser()!.setValue(gender, forKey: "gender")
PFUser.currentUser()!.setValue(hostCount, forKey: "hostCount")
PFUser.currentUser()!.saveInBackground()
}
}
}
}
}
I use this solution, hope it helps you. If you have a question on it, I can answer :)
func notLoggedIn() -> Bool {
let user = PFUser.currentUser()
// here I assume that a user must be linked to Facebook
return user == nil || !PFFacebookUtils.isLinkedWithUser(user)
}
func loggedIn() -> Bool {
return !notLoggedIn()
}
func performNewUser(){
if notLoggedIn() {
return
}
let user = PFUser.currentUser() // Won't be nil because is logged in
// RETURN IF WE ALREADY HAVE A USERNAME AND FBID (note that we check the fbId because Parse automatically fills in the username with random numbers)
if let fbId = user["fbId"] as? String {
if !fbId.isEmpty {
displayAlert("Erreur", error: "Il existe déjà un utilisateur avec ce compte Facebook")
println("we already have a username and fbId -> return")
return
}
}
// REQUEST TO FACEBOOK
println("performing request to FB for username and IDF...")
if let session = PFFacebookUtils.session() {
if session.isOpen {
println("session is open")
FBRequestConnection.startForMeWithCompletionHandler({ (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
println("done me request")
if error != nil {
println("facebook me request - error is not nil :(")
} else {
println("facebook me request - error is nil :)")
println(result)
println(result.name)
println(result.objectID)
// Save to Parse:
var FBSession = PFFacebookUtils.session()
var currentUser = PFUser.currentUser()
var userToSave = PFObject(className: "Utilisateurs")
var accessToken = FBSession.accessTokenData.accessToken
let url = NSURL(string: "https://graph.facebook.com/me/picture?type=large&return_ssl_resources=1&access_token="+accessToken)
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
let image = UIImage(data: data)
currentUser["image"] = data
currentUser.save()
self.performSegueWithIdentifier("connexionApplicationInscriptionViaFacebook", sender: self)
})
let firstName = result["first_name"] as String
let status = "Client"
currentUser.username = result["last_name"] as String
currentUser.email = result.email
userToSave.setObject(currentUser.username, forKey: "nom")
userToSave.setObject(currentUser.username, forKey: "username")
userToSave.setObject(firstName, forKey: "prenom")
userToSave.setObject(status, forKey: "status")
currentUser.setValue(self.tfPrenom.text, forKey: "name")
currentUser.setValue(result.objectID, forKey: "fbId")
currentUser.saveEventually() // Always use saveEventually if you want to be sure that the save will succeed
}
})
}
}
}
After updating to Parse 1.7.4 and deleting the old PFFacebookUtils Framework (keeping the PFFacebookUtilsV4) seems to have fixed the problem by itself! I hope this answer helps other people with the same problem.
I want to fetch the username of the user in username field into the parse.
I am using loginWithFacebook(withcompletionHandler) and fetchUserInforFromFacebook(withcompletionHandler) to fetch userinfo but I have a problem: These methods create an own object and store in parse username field, but I want to get the user username.
func loginWithFacebook(withcompletionHandler: (success:Bool) ->()){
var permissions : Array = [ "user_location","public_profile"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions, {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
self.fetchUserInforFromFacebook(withcompletionHandler)
println("User SIGNED UP and logged in through Facebook!")
}
withcompletionHandler(success: true)
println("User logged in through Facebook!")
} else {
println("Uh oh. The user cancelled the FACEBOOK LOGIN.")
self.showErrorMessage(error!)
withcompletionHandler(success: false)
}
})
}
func fetchUserInforFromFacebook(withcompletionHandler: (success:Bool) ->()){
if ((FBSDKAccessToken.currentAccessToken()) != nil){
var request = FBSDKGraphRequest(graphPath:"me", parameters:nil)
request.startWithCompletionHandler({connection, result, error in
if error == nil {
//FACEBOOK DATA IN DICTIONARY
var userData = result as NSDictionary
var currentUser : PFUser = PFUser.currentUser()
currentUser.setObject(userData.objectForKey("id") as String, forKey: "faceBookID")
currentUser.setObject( userData.objectForKey("name") as String, forKey: "fullName")
currentUser.email = userData.objectForKey("email") as? String
currentUser.username = userData.objectForKey("email") as? String
var location = userData.objectForKey("location") as? NSDictionary
var locName = location?.objectForKey("name") as? String
if let loc = locName {
var fullNameArr = split(loc) {$0 == ","}
var city: String? = fullNameArr.count > 0 ? fullNameArr[0] : nil
var contry: String? = fullNameArr.count > 1 ? fullNameArr[1]: nil
currentUser.setObject(userData.objectForKey("country"), forKey: "countryName")
currentUser.setObject(userData.objectForKey("city"), forKey: "cityName")
}
currentUser.saveInBackground()
withcompletionHandler(success: true)
}else{
println("Error")
self.showErrorMessage(error)
withcompletionHandler(success: false)
}
})
}
}
FBSession.openActiveSessionWithReadPermissions(["public_profile", "email", "user_friends"] , allowLoginUI: true, completionHandler: { (session:FBSession!, state:FBSessionState, error:NSError!) -> Void in
if (error==nil)
{
FBRequest.requestForMe().startWithCompletionHandler({ (connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if (error==nil)
{
// get All Facebook data from user
//http://graph.facebook.com/67563683055/picture?type=square
//NSLog("%#",result as! NSDictionary)
var bUserFacebookDict = result as! NSDictionary
bstrFirstName = bUserFacebookDict.objectForKey("first_name") as! String
bstrLastName = bUserFacebookDict.objectForKey("last_name") as! String
bstrUserName = bUserFacebookDict.objectForKey("name") as! String
}
else
{
//Utility.showErrorAlert(error.description)
}
})
}
})
Much easier approach to get the username:
Firstly you need to call the FBSession method to get basic profile info and ID of the user.
Secondly Once we get user FB ID, we can directly pass the FB ID in graph API: https://graph.facebook.com/?id=1008223822 aand get the username in the following json format:-
{
"id": "1008223822",
"first_name": "Dj\u00e9",
"gender": "male",
"last_name": "Destolicci",
"link": "https://www.facebook.com/dje.destolicci",
"locale": "fr_FR",
"name": "Dj\u00e9 Destolicci",
"username": "dje.destolicci"
}
Here is code:-
//first do simple login and authenticate user to get basic profile info and FB ID
FBSession.openActiveSessionWithReadPermissions(["public_profile", "email", "user_friends"] , allowLoginUI: true, completionHandler: { (session:FBSession!, state:FBSessionState, error:NSError!) -> Void in
if (error==nil)
{
FBRequest.requestForMe().startWithCompletionHandler({ (connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
if (error==nil)
{
var bUserFacebookDict = result as! NSDictionary
let FB_USER_ID = bUserFacebookDict["id"]! as! String
// now call FB graph API to to Get username of the user.
var graphProfileURL = NSURL(string: "https://graph.facebook.com/?id=\(FB_USER_ID)")
var request1: NSURLRequest = NSURLRequest(URL: graphProfileURL!)
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?
>=nil
var error: NSErrorPointer = nil
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request1, returningResponse: response, error:nil)!
var err: NSError
println(response)
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
println("Synchronous\(jsonResult)")
let FB_USER_NAME = jsonResult["username"]! as! String //finally you will get username
}
else
{
//Utility.showErrorAlert(error.description)
}
})
}
})