Facebook iOS SDK and Swift: how to get user's hometown? - ios

I am working with iOS 9.2 & Swift 2.1 & FBSDKVersion: 4.7.0.
I tried with Graph API Explorer, at that time I am getting the desired output.
The converted code is in Objective-C and I changed it to Swift.
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "hometown"], HTTPMethod: "GET")
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil){
print("Error: \(error)")
}
else{
print("fetched details: \(result)")
})

See below example and add hometown option into "fields" parameter of FBSDKGraphRequest object and also change:
func fetchUserProfile()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id, email, name, picture.width(480).height(480)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
print("Error took place: \(error)")
}
else
{
print("Print entire fetched result: \(result)")
let id : NSString = result.valueForKey("id") as! String
print("User ID is: \(id)")
if let userName = result.valueForKey("name") as? String
{
self.userFullName.text = userName
}
if let profilePictureObj = result.valueForKey("picture") as? NSDictionary
{
let data = profilePictureObj.valueForKey("data") as! NSDictionary
let pictureUrlString = data.valueForKey("url") as! String
let pictureUrl = NSURL(string: pictureUrlString)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let imageData = NSData(contentsOfURL: pictureUrl!)
dispatch_async(dispatch_get_main_queue()) {
if let imageData = imageData
{
let userProfileImage = UIImage(data: imageData)
self.userProfileImage.image = userProfileImage
self.userProfileImage.contentMode = UIViewContentMode.ScaleAspectFit
}
}
}
}
}
})
}
Also refer to this link
Fetching user details from Facebook in iOS

Related

From FBSDKGraphRequest to Storyboard

i'm total beginner in coding, but i have a big question :)
I dont know how to get information to display on Main Storyboard form FBSDKGraphRequest.
What i should do next to get picture to Storyboard? I hope someone can help me :)
Using Swift 3, Xcode 8
Facebook login is working and code is:
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){
self.dict = result as? [String : AnyObject]
print(result!)
print(self.dict)
}
})
}
I see it as four steps -- my apologies to you if you already know some of this.
Drag an UIImageView from the object library in interface builder to a view in your storyboard.
Connect the UIImageView to your code as an IBOutlet and name it. Do this by control dragging from your new UIImageView to your code, and then in the popup specify an outlet and name the UIImageView. In my case I named it 'facebookPicture'
Get the URL for the image from the FaceBook result. The following sample code drills down into the result dictionary step by step. There are many ways to shorten this.
#IBOutlet var facebookPicture: UIImageView!
func getFBUserID(){
if((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(
completionHandler: {
[weak self] (connection, result, error) -> Void in
guard let strongSelf = self else { return }
if let error = error {
print("Failed to download FB user with error:. \(error)")
}
if (error == nil) {
let resultDictSwift = result as! Dictionary<String, Any>
if let picture = resultDictSwift["picture"] as? Dictionary<String, Any> {
if let pictureData = picture["data"] as? Dictionary<String, Any> {
if let pictureURL = NSURL(string: (pictureData["url"] as? String)! ) {
strongSelf.downloadImage(url: pictureURL as URL)
}
}
}
print(result!)
let FBID = resultDictSwift["id"]
strongSelf.facebookID = FBID as! String?
print("User FB id: \(strongSelf.facebookID!)")
}
})
}
}
Download the image from the URL location. The following does this asynchronously and uses a previous stack overflow answer here When the download is complete, it sets the result of the download to be the image in your UIImageView
func getDataFromUrl(url: URL, completion: #escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error)
}.resume()
}
func downloadImage(url: URL) {
print("Download Started")
getDataFromUrl(url: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
DispatchQueue.main.async() {
self.facebookPicture.image = UIImage(data: data)
}
}
}
I hope this helps!
In Swift 3
#IBAction func btnFacebookTapped(_ sender: UIButton)
{
let loginManager = FBSDKLoginManager()
loginManager.logIn(withReadPermissions: ["user_about_me", "email" , "user_birthday","user_hometown"], from: self) { (loginResult, error) in
if error != nil
{
self.showalert(strMessage: (error?.localizedDescription)!)
}
else
{
if loginResult?.grantedPermissions == nil
{
self.showalert(strMessage: "Login Permissions not granted")
return
}
if (loginResult?.grantedPermissions.contains("email"))!
{
self.getFBUserData()
}
}
}
}
func getFBUserData()
{
FBSDKGraphRequest.init(graphPath: "me?fields=id,name,email,first_name,last_name,cover,picture.type(large),gender,birthday,hometown", parameters: nil).start(completionHandler: { (connection , result , error ) in
if(error == nil){
DispatchQueue.main.async {
let dictionary = result as! NSDictionary
print(dictionary)
print("Name : \(dictionary.value(forKey: "name")!)")
print("FB ID : \(dictionary.value(forKey: "id")!)")
}
}else{
self.showalert(strMessage: "Somthig Went Wrong..!")
}
})
}

Cannot convert value of type FBSDKGraphRequestHandler

I'm getting the following error when I try to make a data request using the Facebook SDK:
Cannot convert value of type '(_,_,_) throws -> Void' to expected argument type 'FBSDKGraphRequestHandler!'
Here is the relevant code where the error is occurring. I found this in a tutorial but I think it worked with older versions of XCode. I'm using the latest version 7.2.1.
UPDATED
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, gender, email"])
graphRequest.startWithCompletionHandler ({ [weak self] connection, result, error in
if error != nil {
//onError()
print(error)
return
} else {
//get results
PFUser.currentUser()?["gender"] = result["gender"]
PFUser.currentUser()?["name"] = result["name"]
try PFUser.currentUser()?.save()
let userId = result["id"] as! String
let facebookProfilePictureUrl = "https://graph.facebook.com/" + userId + "/picture?type=large"
if let fbpicUrl = NSURL(string: facebookProfilePictureUrl) {
if let data = NSData(contentsOfURL: fbpicUrl) {
self.profilePic.image = UIImage(data: data)
let imageFile:PFFile = PFFile(data: data)!
PFUser.currentUser()?["image"] = imageFile
try PFUser.currentUser()?.save()
}
}
}
})
Thanks!
PICTURE (click on the image to make it larger)
http://imgur.com/skCa1VB
I hope you are using the latest FBSDK in that the completionHandler: has been changed. See the below code:
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: param)
graphRequest.startWithCompletionHandler { [weak self] connection, result, error in
if error != nil {
//onError()
print(error.description)
return
}else{
let fbResult = result as! Dictionary<String, AnyObject>
//Do You rest of the code here
}
})

Can't return output of closure using graph api

If I call this method to obtain a Facebook profile picture it does not work, response gets printed with the data but when I return it its nil, can anyone help?
func getProfilePicture() -> NSData?{
var response:NSData?
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"picture.type(large)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if error != nil {
print("login error: \(error!.localizedDescription)")
return
}
let json = JSON(result)
let profilePicture = json["picture"]["data"]["url"].stringValue
if let url = NSURL(string: profilePicture) {
if let pictureData = NSData(contentsOfURL: url){
response = pictureData
}
}
})
print(response)
return response
}
The Facebook call is using an async completionblock and your return statement will return nil before the call is done loading. That is why you also should use a completion block in your method.
Here is an example how to do this:
func getProfilePicture(completion: (pictureData: NSData?, error: NSError?) -> Void) {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"picture.type(large)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
var pictureData: NSData?
let json = JSON(result)
let profilePicture = json["picture"]["data"]["url"].stringValue
if let url = NSURL(string: profilePicture) {
pictureData = NSData(contentsOfURL: url)
}
completion(pictureData: pictureData, error: error)
})
}
You can call this code like this:
self.getProfilePicture {(pictureData, error) -> Void in
if error != nil {
print("login error: \(error!.localizedDescription)")
}
print(pictureData)
}

Swift FacebookSDK Graphrequest Completion Handler not called

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?

Get array of facebook albums in swift using Facebook SDK 4.1

I'm attempting to fetch an array of a users facebook albums via the new Facebook SDK 4.1 using the following Swift code:
func getAlbumList()
{
var FBAlbums = [String]()
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me?fields=albums", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println("fetched data: \(result)")
let graphData = result.valueForKey("data") as Array;
for obj:FBGraphObject in graphData{
let desc = obj.description;
println(desc);
let name = obj.valueForKey("name") as String;
println(name);
}
}
})
}
The FB SDK query is working ok as the result value contains all the data from facebook (it prints fine), however any attempt to actually turn this into an array is failling.
Using XCode 6.3 this gives the following errors:
let graphData = result.valueForKey("data") as Array; = 'AnyObject?' is not convertible to 'Array<T>'
for obj:FBGraphObject in graphData{ = Use of undeclared type 'FBGraphObject'
I can't seem to find any information about what has replaced FBGraphObject, or why I can't convert the result to an array.
Articles used as background (but out of date it seems):
Creating an Array of objects from the Facebook SDK in Swift
http://selise.ch/build-a-facebook-album-browser-using-swift/
Just change this line of your code:
let graphData = result.valueForKey("data") as Array;
To:
self.dict = result["data"] as! NSArray
This works for me retrieving user photos from facebook:
FBSDKGraphRequest(graphPath: "me/photos", parameters: ["fields": "id, name, source"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
self.dict = result["data"] as! NSArray
for item in self.dict { // loop through data items
if let urlString = item["source"]! {
let url = NSURL(string: urlString as! String)
let imageData = NSData(contentsOfURL: url!)
let image = UIImage(data: imageData!)
self.socialPhotoCollection.append(image!)
}
}
}
})
This is for getting all albums in a different way
Swift 3x:
FBSDKGraphRequest(graphPath: "/me/albums", parameters: ["fields":"id,name,user_photos"], httpMethod: "GET").start(completionHandler: { (connection, result, error) in
print(result!)
})

Resources