So i'm trying to get a users Facebook profile image using SLRequest. I feel like I've scoured the entire internet to no avail and am at my wits end. Here's the dilemma...
Version 1 of the code:
let store = ACAccountStore()
let type = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
store.requestAccessToAccountsWithType(type, options: [ ACFacebookAppIdKey: "1437725166510606", ACFacebookPermissionsKey: ["email"] ]) { (granted: Bool, error: NSError!) -> Void in
if granted {
let accounts = store.accountsWithAccountType(type)
if let account = accounts.last as? ACAccount {
let pictureURLString = "https://graph.facebook.com/v2.1/me/picture"
let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: NSURL(string: pictureURLString), parameters: nil)
request.account = account
request.performRequestWithHandler() { (data: NSData!, response: NSHTTPURLResponse!, error: NSError!) -> Void in
if let imageData = data {
// Save the image
// println("Data size: \(imageData.length)\ndata: \(imageData.description)\nAs string: \(NSString(data: imageData, encoding: NSUTF8StringEncoding))")
data.writeToFile(NSFileManager.defaultManager().profileImagePath(), atomically: true)
}
}
}
}
}
Ok, so this versions works, but returns a really, really small version of the profile image. I want a larger image! According to the Facebook docs, and lot's of others on SO the way to do this is to specify parameters such as: type=large or width=120&height=120 but as soon as I do this I get the following error:
{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}}
When the Facebook docs for getting the profile image (at https://developers.facebook.com/docs/graph-api/reference/v2.1/user/picture) explicitly state:
Because profile pictures are always public on Facebook, this call does not require any access token.
Many suggestions, such as this answer https://stackoverflow.com/a/7882628/1175289, suggest using the Facebook id rather than "me" in the request, but this does not seem to work at all now that we get an app_scoped_user_id rather than the canonical fbId.
EDIT: This works fine, I was just being a plank! :)
For the sake of sanity, here is the code that causes the error:
let store = ACAccountStore()
let type = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
store.requestAccessToAccountsWithType(type, options: [ ACFacebookAppIdKey: "1437725166510606", ACFacebookPermissionsKey: ["email"] ]) { (granted: Bool, error: NSError!) -> Void in
if granted {
let accounts = store.accountsWithAccountType(type)
if let account = accounts.last as? ACAccount {
let pictureURLString = "https://graph.facebook.com/v2.1/me/picture?type=large"
let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: NSURL(string: pictureURLString), parameters: nil)
request.account = account
request.performRequestWithHandler() { (data: NSData!, response: NSHTTPURLResponse!, error: NSError!) -> Void in
if let imageData = data {
// Save the image
// println("Data size: \(imageData.length)\ndata: \(imageData.description)\nAs string: \(NSString(data: imageData, encoding: NSUTF8StringEncoding))")
data.writeToFile(NSFileManager.defaultManager().profileImagePath(), atomically: true)
}
}
}
}
}
as you can see, the only thing that has changed is the addition of ?type=large to the url string.
If anyone has faced a similar issue, or has any idea what I'm doing wrong, help would be very much appreciated! :)
Because you are using /me/
in your API call, an access_token
is required because the API doesn't know who me
is. If you replace this with a User ID, e.g.
https://graph.facebook.com/v2.1/4/picture?type=large
It should work fine.
If you want to continue using /me/
in the URL, just append the user's access_token
to the URL too, e.g.:
https://graph.facebook.com/v2.1/4/picture?type=large&access_token=abcdef