Facebook graph API link parameter returning nil - ios

I am trying to store a logged in facebook user's facebook username (eg www.facebook.com/james.dean01) in order to connect people via messenger (similar to How to open Facebook Messenger and direct to someone?). I am configuring a button which will send a user directly to someones messenger chat but to do so I need their username/facebook URL. I am attempting to use the "link" property (Facebook graph API: https://developers.facebook.com/docs/graph-api/reference/user) to obtain a link to the user's profile which could be used for this purpose, only the link property (printed) returns nil. I am not sure what I am doing wrong. The aim is that each time a user logs in the data is read and the database is updated. Below is the code.
Any help would be greatly appreciated!
import FacebookCore
class FacebookService {
static let instance = FacebookService()
let params = ["fields": "email, first_name, last_name, link, picture, name"]
func recordUserData() {
let graphRequest = GraphRequest(graphPath: "me", parameters: params)
graphRequest.start {
(urlResponse, requestResult) in
switch requestResult {
case .failed(let error):
print("error in graph request:", error)
break
case .success(let graphResponse):
if let responseDictionary = graphResponse.dictionaryValue {
print(responseDictionary)
let link = responseDictionary["link"] as? String
let email = responseDictionary["email"] as? String
let fbId = responseDictionary["id"] as? String
let name = responseDictionary["name"] as? String
let picture = responseDictionary["picture"] as? NSDictionary
let data = picture!["data"] as? NSDictionary
let url = data!["url"] as? String
print("Link: \(link)")
print(url)
}
}
}
}
}

You need to ask for the necessary permission, https://developers.facebook.com/docs/facebook-login/permissions#reference-user_link
And the use of this permission requires review by Facebook, before you can use it in your live app.
Not sure you would get this through review though, because what you would be doing is essentially what it says there is a not allowed use case:
Attempt to programmatically determine someone's Facebook username or canonical User ID.
So no guarantee Facebook will approve this; you can only try and submit it for review and see what feedback you get.

Related

Get User's friends user ID for app leaderboard scores

So, i'm creating a leaderboard where users can see global scores, regional scores and friends scores who have used the app before. all these scores are fetched and written to the fire store database in firebase along with the user's unique id when they log in with facebook.
I need to get a list of the users friends and their user ids from facebook so I can search the fire store database for their scores using the Facebook id. But I don't know how to get the id out of my result below when getting the list of friends:
func getFriendsFromFB() {
let params = ["fields": "id, first_name, last_name, name, email, picture"]
let graphRequest = FBSDKGraphRequest(graphPath: "/me/friends", parameters: params)
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error == nil {
if let userData = result as? [String:Any] {
print(userData)
}
} else {
print("Error Getting Friends \(error)");
}
})
connection.start()
}
Can someone suggest how I get the user id out of my result in the code above?
Also I do ask for the user_friends permission when asking the user to login.
You're casting the result as a Dictionary, this means the results are stored as key values. You can retrieve values by using dictionary["keyHere"]. I'm not sure how the FB graph result is structured, but you will have to do something like this:
// Don't continue if the result is not a dictionary
guard let userData = result as? [String: Any] else {
return
}
// Now, you can get values from the dictionary
// Let's say the userID is a String
if let userID = userData["id"] as? String {
print(userID)
}

Save data in specific user id iOS - Alamofire, Json

I have a job application app that when a user registers through a registration page, it is automatically generating a unique user_id for each user. This app also supports multiple different data for each user (e.g education details, experience etc) so these data have to be connected with the user id of the corresponding user.
For example, suppose user A registers a new account with user_id ABCD. When this user adds new information to the system, the data have to be linked back to this user_id, ABCD. Likewise, if a user B registers a new account with user_id EFGH, any new data added to the system by user B, the data have to be linked back to his/her user_id, EFGH.
How could I do that in iOS using Swift?
Alamofire.request(URL_USER_COMPANY_PROFILE, method: .post, parameters: parameters).responseJSON
{
response in
// Printing response
print(response)
// Getting the json value from the server
if let result = response.result.value {
// Converting it as NSDictionary
let jsonData = result as! NSDictionary
UserDefaults.standard.value(forKey: "user_id")
}
}
I found the answer with iPhone developer # Muhammed Azharuddin, by creating a class for user defaults to store datas in user_id
extension UserDefaults{
static let isLoggedIn = "com.xyz.AlotTest1isLoggedIn"
static let userId = "com.xyz.AlotTest1userId"
}
And call this extension in parameters after #IBAction
let parameters: Parameters=[
"institute_name":univ.text!,
"degree_name":grad.text!,
"start_year":cityP.text!,
"end_year":enYear.text!,
"degree_city":proj.text!,
"degree_country":eduCountry.text!,
"user_id" : AuthService.instance.userId ?? ""
]
print(parameters)
//Sending http post request
Alamofire.request(URL_USER_EDUCATION, method: .post, parameters: parameters).responseJSON
{
response in
//printing response
print(response)
//getting the json value from the server
if let result = response.result.value {
let re = UserDefaults.standard.value(forKey: "user_id") as! Array<Parameters>
print(result)
let defaults: UserDefaults = UserDefaults.standard
//This class variable needs to be defined every class where you set or fetch values from NSUserDefaults
}

Facebook login using Firebase - Swift iOS

I'm implementing login with Facebook using Firebase, I have this code which searches my database after a successful facebook authentication for the email if exists in database and logs in the app if found, I want to direct the user to registration view controller if not found but its not working since this method is asynchronous. I appreciate if anyone can help. Here is my code :
func getFacebookUserInfo() {
if(FBSDKAccessToken.current() != nil){
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "id,name,gender,email,education"])
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) -> Void in
let data = result as! [String : AnyObject]
let email = data["email"] as? String
let emailRef = FIRDatabase.database().reference().child("usernameEmailLink")
emailRef.queryOrderedByValue().observe(.childAdded, with: { snapshot in
if let snapshotValue = snapshot.value as? [String: AnyObject] {
for (key, value) in snapshotValue {
if(value as? String == email){
self.stringMode = snapshotValue["mode"]! as! String
self.username = key
self.parseUserInfoFromJSON()
return
}
}
}
})
})
connection.start()
}
}
Thank you.
The registration/existence of the user in Firebase should probably be determined before the graphRequest code in the question.
Most importantly, (and this is critical), email addresses are dynamic so they should not be used to verify if a user exists. i.e. user with email address of 'leroy#gmail.com' updates his email to 'leroy.j#gmail.com'. If emails are used to verify registration, it can totally break if that email changes.
Please use Firebase uid's for that purpose as they are static and unique.
Since we only have a small snippet of code, we don't know the exact sequence being used. This answer is pseudo-code to outline a possible sequence.
We assume that by 'registered' it means that the user has gone through some kind of app registration sequence and the user has been created (and now exists/is registered) in Firebase.
In general there would be a login button and a delegate method to handle the actual login action.
The user enters their login and taps the login button
func loginButton(loginButton: FBSDKLoginButton!,
didCompleteWithResult result: FBSDKLoginManagerLoginResult!,
error: NSError?) {
Firebase can then get the credentials for that user (see Firebase doc quote below)
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
At that point, sign in the user and check to see if they are registered (exist) in the Firebase user node.
FIRAuth.auth()?.signIn(with: credential) { (user, error) in
if let error = error { //failed due to an error
return
}
let uid = user.uid //the firebase uid
let thisUserRef = userRef.child(uid) //a reference to the user node
//check to see if the user exists in firebase (i.e. is Registered)
thisUserRef.observeSingleEvent(of: .value, with: { (snapshot) in
//if snapshot exists
//then the user is already 'registered' in the user node
// so continue the app with a registered user
//if not, then need to have the user go through a registration sequence and
// then create the user (make them registered) in the user node
doRegisterUser(user)
})
func doRegisterUser(user: FIRUser) {
//get what you need from the user to register them
// and write it to the users node. This could be from additional
// questions or from their Facebook graph, as in the code in the
// question
//for this example, we'll just write their email address
let email = user.email
let dict = ["email": email]
//create a child node in the users node with a parent of uid
// and a child of email: their email
thisUserRef.setValue(node)
//next time the user logs in via FB authentication, their user node
// will be found as they are now a 'registered' user
}
From the Firebase docs
After a user signs in for the first time, a new user account is
created and linked to the credentials—that is, the user name and
password, or auth provider information—the user signed in with. This
new account is stored as part of your Firebase project, and can be
used to identify a user across every app in your project, regardless
of how the user signs in.
As I mentioned, this is very pseudo code but offers a possible sequence for a solution.

iOS: Get Latest Tweet Text Only From Specific User

I am wanting to get the latest tweet from a specific user that will not change. So if the specific user was Joe Smith, I would always get the latest tweet from him. I've looked into Fabric which seems to only get specific tweets by ID. The Twitter API looks fairly involved when all I am wanting is the latest tweet from a user. What is the best way to do this?
you could achive this by searching for a user and only using th first element
Using from:#tweethandle for example: from:StackOverflow and using only the first item!
You can search using TWTRAPIClient's URLRequestWithMethod
Ex: (using SwiftyJSON for parsing JSON) this should print the first tweet
let twError:NSErrorPointer = nil
let userID = Twitter.sharedInstance().sessionStore.session()?.userID
let client = TWTRAPIClient(userID: userID)
let request = client.URLRequestWithMethod("GET", URL: "https://api.twitter.com/1.1/search/tweets.json", parameters: ["q":"from:StackOverflow","result_type":"recent"], error: twError)
if twError == nil {
client.sendTwitterRequest(request, completion: { (response, data, error) -> Void in
let json = JSON(data: data!)
print(json["statuses"][0])
})
}
More info in the docs

Trouble retrieving list of facebook friends from json data in swift

I am using FBSDK in my Swift iOS application and currently I am trying to retrieve the list of friends who also use my app. I have two-three people who should show up but whenever I search the graphrequest result for friends it returns nil..
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result:AnyObject!, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
//get Facebook ID
let faceBookID: NSString = result.valueForKey("id") as NSString
//get username
let userName : NSString = result.valueForKey("name") as NSString
//get facebook friends who use app
let friendlist: AnyObject = result.valueForKey("friends") as AnyObject
}
I have the "email", "user_friends", and "public_profile" permissions which should be enough to retrieve this information. Any Ideas on what I am doing wrong?? this is doing my head in as my friend doing an android version has successfully got his working..
My problem here was that I never Actually requested for the list of friends in my facebook graph request...
after replacing FBSDKGraphRequest(graphPath: "me", parameters: nil)
with FBSDKGraphRequest(graphPath: "me?fields=id,name,friends", parameters: nil)
I was able to retrieve the list of friends because the response actually contained information for this. A very trivial mistake on my part.
In v2.0 of the Graph API, you must request the user_friends permission
from each user. user_friends is no longer included by default in every
login. Each user must grant the user_friends permission in order to
appear in the response to /me/friends.
see here : https://developers.facebook.com/bugs/1502515636638396/

Resources