facebookfacebook-graph-apiios7slrequest

iOS7 Access user Facebook Profile Picture


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! :)


Solution

  • 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