I am trying to retrieve a list of the user's Facebook friends that are using the app. To my knowledge, this permission is granted automatically but please do correct me if I'm wrong.
Here is the code I am using to retrieve the list. At the moment it just skips the code in the completion handler without leaving any messages in the console.
let params = ["fields": "id, first_name, last_name, name"]
FBSDKGraphRequest(graphPath: "/me/friends", parameters: params).start { (connection, result, error) in
if error != nil {
print("ERROR: \(error.debugDescription)")
}
else {
if let friendArray : NSArray = (result as! NSDictionary).value(forKey: "data") as! NSArray
{
for friend in friendArray {
print("Name \((friend as AnyObject).value(forKey: "name"))")
}
}
}
}
Unfortunately I can't seem to find any up to date documentation on this topic.
Related
I'm trying to get the user Facebook friends count in Swift 3, but I found some problems:
First of all, I created this code based on Facebook Documention:
func getNumberOfFriends() {
let parameters = ["fields": "summary"]
FBSDKGraphRequest(graphPath: "me/friends", parameters: parameters, httpMethod: "GET").start { (connection, result, error) in
let userInformations = User.instance
if let error = error {
print("erro: \(error.localizedDescription)")
return
}
if let result = result as? [String: AnyObject] {
if let summary = result["summary"] as? NSDictionary {
if let total_count = summary["total_count"] as? Int {
userInformations.numberOfFriends = total_count
self.getFriendsCountDelegate?.didGetFriendsCount(error:false)
}
}
}
}
}
The problem is that I'm receiving an empty data response. I think the problem could be a strange thing I found in my Login: I'm requesting these permissions:
var loginButton = FBSDKLoginButton()
self.loginButton.readPermissions = ["public_profile", "user_friends", "email", "user_posts"]
self.loginButton.publishPermissions = ["publish_actions"]
but when I check those permissions, I found that I don't have it! I only have "public_profile" and "publish_actions".
When I check my FacebookApp Page, I see that it seems ok:
All permissions are ok on my Facebook App Page
Does somebody could help me? I don't know what else should I do!
Thank you
I'm using AWS Mobile Hub service for user sign-in. I follow mobile hub developer guide and i was successfully able to login using Facebook. After logging -in how to get the user details like profile picture or name or DOB etc. The developers guide of the mobile hub doesn;t explain this. Is it possible to get the details or is it only to authenticate users?
Currently the AWS Auth SDK which helps you perform Facebook SignIn doesn't support retrieving the user profile information can directly use the Facebook iOS SDK to fetch information including username, imageURL, etc.
let imageGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "picture.type(large)"])
let imageConnection = FBSDKGraphRequestConnection()
imageConnection.add(imageGraphRequest, completionHandler: { (connection, result, error) in
guard let imageResult = result as? NSDictionary else { return}
if let imageURL = URL(string:(((imageResult.value(forKey: "picture") as AnyObject).value(forKey: "data") as AnyObject).value(forKey: "url") as? String)!) {
self.imageURL = imageURL
}
})
imageConnection.start()
let userGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
let userConnection = FBSDKGraphRequestConnection()
userConnection.add(userGraphRequest, completionHandler: { (connection, result, error) in
guard let userResult = result as? NSDictionary else { return }
if let userName = userResult.value(forKey: "name") as? String {
self.userName = userName
}
})
userConnection.start()
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")
})
}
})
}
}
})
}
I have two users logged in with publish_actions set to friends but on both users /appID/scores only returns one user's scores. Both are posting scores successfully.
Here is the posting code:
FBSDKGraphRequest(
graphPath: "/me/scores",
parameters: ["score" : finalScore], HTTPMethod: "POST").startWithCompletionHandler { (connection, result, error) in
if error != nil {
print(error)
}
NSNotificationCenter.defaultCenter().postNotificationName(SPostedScoreNotification, object: nil)
complete()
}
And here is the retrieving code:
dispatch_async(dispatch_get_main_queue(), {
FBSDKGraphRequest(graphPath: "/" + appID + "/scores", parameters: ["fields" : "user,score"]).startWithCompletionHandler { (connection, result, error) in
var fbScores = [FBScore]()
guard
let validResult = result,
let data = validResult["data"] as? [[String : AnyObject]]
else {
complete(fbScores)
return
}
for scoreData in data {
if let fbScore = FBScore(attributes: scoreData) {
if NSCalendar.currentCalendar().isDateInToday(fbScore.date) {
fbScores.append(fbScore)
}
}
}
complete(fbScores)
}
})
Figured it out.
You must request public_profile and user_friends first and then publish_actions. I was only requesting publish_actions.
publish_actions must not be set to only_me.
EDIT: The problem with this question is a bit silly. As in the answer the problem is that I have not given the parameters which I want.
I can not get through with it anymore :) What can be the problem?
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
print("Error: \(error)")
}
else
{
print("fetched user: \(result)")
let userName : NSString = result.valueForKey("name") as! NSString
print("User Name is: \(userName)")
let userEmail : NSString = result.valueForKey("email") as! NSString
print("User Email is: \(userEmail)")
}
})
}
I call the function like that:
func loginButton(loginButton: FBSDKLoginButton!,
didCompleteWithResult result: FBSDKLoginManagerLoginResult!,
error: NSError!) {
print("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
returnUserData()
}
}
}
I get the error:
My problem is about the fatal error. However, I am kindly waiting for the comments on 2nd and 3rd lines of the output. Because, I get this output every time but the app runs correctly.
You must specify the parameters for the request.
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "first_name, last_name, email"])