I'm trying to add a Facebook friend list to my Swift iOS app using the Graph API.
I'm struggling to work out how to actually access the data that's being send back from Facebook.
The response I get looks like this:
success(FacebookCore.GraphResponse(rawResponse: Optional({
"first_name" = Jamie;
id = 1626917907360895;
"last_name" = McAllister;
name = "Jamie McAllister";
picture = {
data = {
height = 50;
"is_silhouette" = 0;
url = "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/12994335_1101318013254223_4481895970110564364_n.jpg?oh=d10209f113213981e4417e7f6f3f82d8&oe=5A91F135";
width = 50;
};
};
})))
My graph Request is just /me for now as I'm the only registered user. But all the fields in the response are what I will be requesting from the friends list
The graph request looks like this:
var graph = GraphRequest.init(graphPath: "me")
graph.parameters = ["fields": "id, first_name, last_name, middle_name, name, email, picture"]
graph.start({ (response, data) in
print("======GRAPH=====")
print(data)
})
So, I want to be able to take the GraphResponse, make it an Array and assign it to a variable. I am completely stumped by this one.
Hope this Helps
Swift 4.2
func getFbId(){
if(AccessToken.current != nil){
let req = GraphRequest(graphPath: "me", parameters: ["fields": "email,first_name,last_name,gender,picture"], accessToken: AccessToken.current, httpMethod: GraphRequestHTTPMethod(rawValue: "GET")!)
req.start({ (connection, result) in
switch result {
case .failed(let error):
print(error)
case .success(let graphResponse):
if let responseDictionary = graphResponse.dictionaryValue {
print(responseDictionary)
let firstNameFB = responseDictionary["first_name"] as? String
let lastNameFB = responseDictionary["last_name"] as? String
let socialIdFB = responseDictionary["id"] as? String
let genderFB = responseDictionary["gender"] as? String
let pictureUrlFB = responseDictionary["picture"] as? [String:Any]
let photoData = pictureUrlFB!["data"] as? [String:Any]
let photoUrl = photoData!["url"] as? String
print(firstNameFB, lastNameFB, socialIdFB, genderFB, photoUrl)
}
}
})
}
}
The Graph request start completion block has changed to requiring 3 arguments instead of 2.
So you will have something like this (NOTICE THERE ARE NOW 3 ITEMS PASSED IN THE START BLOCK [connection, result, and error]):
let params = ["fields" : "email, first_name, id, picture"]
let graphRequest = GraphRequest(graphPath: "me", parameters: params)
graphRequest.start{
(connection, result, error in
if error == nil {
if let responseDictionary = result as? NSDictionary {
UserProfile.userName = responseDictionary["first_name"] as? String ?? "User"
UserProfile.userID = responseDictionary["id"] as! String
var pictureUrl = ""
if let picture = responseDictionary["picture"] as? NSDictionary, let data = picture["data"] as? NSDictionary, let url = data["url"] as? String {
pictureUrl = url
}
}
}else{
print("error in graph request:", error)
}
To read response from Facebook Graph Request use the below line of codes
let info = data as! [String : AnyObject]
if info["name"] as? String != nil {
self.usernameLbl.text = info["name"] as! String
}
Hope this will help you
Related
I have referred this link.
https://developers.facebook.com/docs/pages/getting-started but could not get answer.
I need "134902671......?s_bl=1&s_sc=134902691.....&s_sw=0&s_vt=api-s&a=AbyURQDWoQ-jNWNr" this stream key of page.
func getPageDetail(dict: [String:Any]) {
var request: GraphRequest?
let accessToken = AccessToken.current?.tokenString
print("{accessToken-\(accessToken)-}")
let params = ["access_token" : dict["access_token"] as! String,
"page_id" : dict["id"] as! String
]
request = GraphRequest.init(graphPath: "/me/live_videos?access_token=\(accessToken!)", parameters: params, httpMethod: HTTPMethod(rawValue: "POST"))
request?.start(completionHandler: { (_, result, _) in
print("result-........\(result)-")
let dict = result as! NSDictionary
let id = dict.value(forKey: "id") as! String
let streamUrlStr = dict.value(forKey: "stream_url") as! String
let lastCom = streamUrlStr.components(separatedBy: "/")
let finalStr = lastCom.last!
print(finalStr)
})
}
The finalStr which I am getting here does not match the stream key which is there in the page.
I'm using the new facebook graph request and after updating pods I get an error
< Use of undeclared type 'GraphRequestResult'>
let graphRequest = GraphRequest(graphPath: kGraphPathMe, parameters: ["fields":"id,email,last_name,first_name,picture"], tokenString: accessToken.tokenString, version: .init(), httpMethod: .get)
graphRequest.start {(response: HTTPURLResponse?, result: GraphRequestResult<GraphRequest>) in
switch result {
case .success(let graphResponse):
if let dictionary = graphResponse.dictionaryValue {
completion(FacebookUser(jsonDict: dictionary))
}
break
default:
print("Facebook request user error")
}
}
check this code
let parameters = ["fields": "email, id, name"]
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: parameters)
_ = graphRequest?.start { [weak self] connection, result, error in
// If something went wrong, we're logged out
if (error != nil) {
// Clear email, but ignore error for now
return
}
// Transform to dictionary first
if let result = result as? [String: Any] {
// Got the email; send it to Lucid's server
guard let email = result["email"] as? String else {
// No email? Fail the login
return
}
guard let username = result["name"] as? String else {
// No username? Fail the login
return
}
guard let userId = result["id"] as? String else {
// No userId? Fail the login
return
}
}
} // End of graph request
This question already has answers here:
Type 'Any?' has no subscript members [duplicate]
(2 answers)
Closed 6 years ago.
I am using Facebook SDK for login and fetching data at my end but unable to solve the issue I am facing challenges related to syntax
func fetchProfile() {
let parameters = ["fields": "email, first_name, last_name, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: parameters).start(completionHandler: { (connection, user, requestError) -> Void in
if requestError != nil {
print(requestError)
return
}
var email = user["email"] as? String
let firstName = user["first_name"] as? String
let lastName = user["last_name"] as? String
self.nameLabel.text = "\(firstName!) \(lastName!)"
var pictureUrl = ""
if let picture = user["picture"] as? NSDictionary, let data = picture["data"] as? NSDictionary, let url = data["url"] as? String {
pictureUrl = url
}
})
}
In the line var email = user["email"] as ? String i getting error as type any? has no transcript.
Try this:
if let dataDict = user as? [String:AnyObject] {
var email = dataDict["email"] as? String
let firstName = dataDict["first_name"] as? String
let lastName = dataDict["last_name"] as? String
//self.nameLabel.text = "\(firstName!) \(lastName!)"
var pictureUrl = ""
if let picture = dataDict["picture"] as? [String:AnyObject], let data = picture["data"] as? [String:AnyObject], let url = data["url"] as? String {
pictureUrl = url
}
}
You need to convert the user type Any to type Dictionary [String:AnyObject], then only you can use subscripts to extract value from it.
I am using a graph request to get a json using this code:
nextrequest.start({ (response: HTTPURLResponse?, result: Any?) in
print(result)
})
this is the json result below and I have no idea how to access the the data inside such as gender, id and name...
Optional(FacebookCore.GraphRequestResult<FacebookCore.GraphRequest>.success(FacebookCore.GraphResponse(rawResponse: Optional({
gender = male;
id = 1128614937219535;
name = "Rayan Slim";
picture = {
data = {
height = 320;
"is_silhouette" = 0;
url = "https://scontent.xx.fbcdn.net/v/t1.0-1/p320x320/12541113_961418627272501_5451131278168499090_n.jpg?oh=47433bc236ce63ce1c07b92499087f29&oe=586A406A";
width = 320;
};
};
}))))
any help would be greatly appreciated!!!!
After permission has been granted here's the function that works.
if AccessToken.current != nil {
GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start({ (urlResponse, requestResult) in
switch requestResult {
case .Success(let response):
if let responseDictionary = response.dictionaryValue {
let email = responseDictionary["email"] as? String
print(email)
let first = responseDictionary["name"] as? String
print(first)
if let picture = responseDictionary["picture"] as? NSDictionary {
if let data = picture["data"] as? NSDictionary{
if let profilePicture = data["url"] as? String {
print(profilePicture)
}
}
}
}
case .Failed(let error):
print(error)
}
})
}
This is tested and working in Swift 3, using the Facebook SDK for Swift
let pictureRequest = GraphRequest(graphPath: "me/picture?type=large&redirect=false", parameters: [:])
pictureRequest.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)
var dict: NSDictionary!
dict = responseDictionary["data"] as! NSDictionary
print(dict)
print(dict["url"])
}
}
}
if let userDataDict = result as? NSDictionary {
self.first_name = userDataDict["first_name"] as? String
self.id = userDataDict["id"] as? String
self.last_name = userDataDict["last_name"] as? String
let pictDict = userDataDict["picture"] as? NSDictionary
let pictureUrl = pictDict?["data"] as? NSDictionary
self.pictureUrl = pictureUrl?["url"] as? String
}
do like
nextrequest.start({ (response: HTTPURLResponse?, result: Any?) in
print(result)
if let userData = result as? [NSObject: Any]
{
if let name = userData["name"] as? String
{
print(name)
}
if let picture = userData["picture"] as? [NSObject: Any] {
if let data = picture["data"] as? [NSObject: Any] {
if let profilePictureURL = data["url"] as? String {
// Now add the data to the UI elements
print (profilePictureURL)
}
}
}
}
})
Make use of some JSON parser, maybe Unbox that makes it easier to handle JSON. This code is not tested, but it is an outline of how you could do it. It is always code to store data in a struct instead of using dictionaries.
typealias JSON = [String: Any]
protocol Model {
init?(json: JSON)
}
func getDataFromFacebook() {
...
nextrequest.start {
(response: HTTPURLResponse?, result: Any?) in
self.handleFacebookResult(result)
}
}
func handleFacebookResult(_ result: Any?) {
guard
let json = result as? JSON,
let person = Person(json: json)
else { return }
//do something with person! :)
}
struct Person: Model {
let name: String
let gender: String
let picture: Picture
init?(json: JSON) {
guard
let name = json["name"] as? String,
let gender = json["gender"] as? String,
let pictureJson = json["picture.data"] as? JSON, // "picture.data" possible when using 'Unbox'
let picture = Picture(json: pictureJson)
else { return nil }
self.name = name
self.gender = gender
self.picture = picture
}
}
struct Picture: Model {
let height: Int // Or maybe float...?
let width: Int // Or maybe float...?
let url: String
init?(json: JSON) {
guard
let height = json["height"] as? Int,
let width = json["width"] as? Int,
let url = json["url"] as? String
else { return nil }
self.height = height
self.width = width
self.url
}
}
if i implement the following function directly on the viewController everything works fine. (this is not complete, but it works for the picture)
func getFBData() {
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, email, first_name, last_name, picture"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
let email = result.valueForKey("email") as? String
let fbid = result.valueForKey("id") as! String
let fname = result.valueForKey("first_name") as! String
let lname = result.valueForKey("last_name") as! String
let facebookProfileUrl = "http://graph.facebook.com/\(fbid)/picture?type=large"
let url = NSURL(string: facebookProfileUrl)
if let data = NSData(contentsOfURL: url!) {
self.imgProfile.image = UIImage(data: data)
}
}
})
}
}
But instead i tried to keep all the facebook related stuff separated in a FacebookController.swift class.
class func getUserData() -> [String: String] {
var dict: [String: String]?
let token = FBSDKAccessToken.currentAccessToken()
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, email, name, first_name, last_name, picture"])
if((token) != nil) {
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil) {
let fbid = result.valueForKey("id") as! String
let name = result.valueForKey("name") as? String
let fname = result.valueForKey("first_name") as! String
let lname = result.valueForKey("last_name") as! String
let email = result.valueForKey("email") as? String
let pictureURL = "http://graph.facebook.com/\(fbid)/picture?type=large"
dict = ["id": fbid, "name": name!, "fname": fname, "lname": lname, "email": email!, "picture": pictureURL]
print(dict)
} else {
print("ok")
print("\(error)")
}
})
}
return dict!
}
The User is logged in and all the permissions are granted, but when i try to call FacebookController().getUserData() it returns dict, which is nil. I already figured that this is because the completionHandler of the graphRequest never gets called.
Can anybody help?