Facebook Tutorial for iOS: How To Get a User Profile with Facebook’s New Graph API from your iPhone App

Ray Wenderlich
Is She Hot or Not??

Is She Hot or Not??

This article is the second part of a three-part series about how to use Facebooks’s new Graph API in your iPhone app.

In the first part of the series, we covered how to authenticate the user using the Graph API.

In this second article, we’ll cover how to get basic information from the user’s Facebook profile – and we’ll have a little fun along the way! (Jump to Part 3 of the series.)

We’ll also cover how to use JSON framework to parse the response, and ASIHTTPRequest to send the requests.

So let’s get some data with Facebook’s Graph API!

Getting Started

If you haven’t already, grab a copy of the sample project that we developed in the first part of the series, which we will use as our starting point.

Last time we wrote an app that authenticated our user and got an access token. But all we did was print it out!

Obviously that is not very fun. And since after all as iPhone devs most of us are in the business of fun – let’s do something about that!

And what could be more fun than rating hot babes?! (or dudes, if you’re into that kind of thing!)

Hot or Not?

Let’s begin by modifying FBFunViewController.h to add a few more variables that we’ll need for our Hot or Not UI:

// Inside class declaration
UITextView *_textView;
UIImageView *_imageView;
UISegmentedControl *_segControl;
UIWebView *_webView;
NSString *_accessToken;
 
// Afterwards
@property (retain) IBOutlet UITextView *textView;
@property (retain) IBOutlet UIImageView *imageView;
@property (retain) IBOutlet UISegmentedControl *segControl;
@property (retain) IBOutlet UIWebView *webView;
@property (copy) NSString *accessToken;
 
- (IBAction)rateTapped:(id)sender;

Now open up FBFunViewController.xib so we can set up our Hot or Not UI. We need a place for a message, a picture to rate, a hot or not button, and a rate button. We also want an area down at the bottom where users can like our fan page on Facebook if they like this app.

So drag a UITextView, UIImageView, UISegmentedControl, UIButton, and UIWebView over to the view and arrange them like the image below:

Hot or Not Layout

Once you’ve laid it out, do the following as well:

  • Click on the UITextView and uncheck the Editable checkbox.
  • Control-drag from “File’s Owner” to the UITextView, UIImageView, UISegmentedControl, and UIWebView, and connect each of them to the appropriate outlets.
  • Control-drag from the “Rate!” UIButton back to the “File’s Owner” and connect it to the “rateTapped:” outlet.
  • Save the XIB, and now let’s dive into code!

Or actually, let’s not. First we have to take a slight detour and talk a bit more about how the Facebook Graph API works.

Facebook Graph API Overview

The Facebook Graph API is pretty simple. Basically, to get all kinds of information, all you need to do is navigate to a particular URL. For example, you could see my profile information by visiting https://graph.facebook.com/ray.wenderlich.

Note the data comes back in JSON format. Well, after the recent Google Translate and JSON tutorial, this is no problem for us!

There are tons of objects you can access via different URLs, including users, pages, status messages, photos, and more. Far too many to list here, so if you’re interested in a list, take a quick look at the Graph API Introduction on Facebook’s official page.

Note that to access most of these, you need to pass in an access token like we got in the previous Facebook tutorial so Facebook can authenticate you’re allowed to see it.

NSURLRequest and NSURLConnection to the Rescue?

From an iPhone development perspective, our first thought might be to use the NSURLRequest and NSURLConnection classes to simply fire off a request to the above APIs and get a response. This would definitely work – but there’s an even easier way.

You see, one of the beauties of the Graph API is that not only can you GET data from Facebook – you can also POST data to Facebook! So you can post an update to a user’s wall, like a post, attend an event, or much more.

You can do POSTs with NRURLRequest / NSURLConnection, but it gets a bit hairy when dealing with multipart MIME data, which we’ll need when we’re doing things like uploading photos.

So rather than implementing this ourselves by hand, we’ll use a great library made just for this purpose: ASIHTTPRequest!

Integrating ASIHTTPRequest

ASIHTTPRequest is a powerful open source library written by Ben Copsey from All-Seeing Interactive (and he’s a fellow cocos2d developer too!) It makes it easy to post data and files, and has tons of other great features too like cache support, easy access to HTTP headers, cookie support, and much more.

So let’s add ASIHTTPRequest to our project. Take the following steps:

  1. Download the latest version of ASIHTTPRequest.
  2. Back in FBFun, right click FBFun under “Groups & Files”, click “Add\New Group”, and name the group “ASIHTTPRequest”.
  3. Drag all of the files from the “pokeb-asi-http-request-xxx\Classes” to your new group. Make sure “Copy items into destination group’s folder (if needed)” is checked, and click “Add”.
  4. Repeat the above for the 2 files in “pokeb-asi-http-request-xxx\External\Reachability”.
  5. Right click the Frameworks folder, and click “Add\Exisitng Frameworks…”. Choose CFNetwork from the list, and click Add.
  6. Repeat the above for SystemConfiguration.framework, MobileCoreServices.framework, CoreGraphics.framework and libz.1.2.3.dylib (at the bottom of the list).
  7. Compile your project. If it works, you’re integrated!

We’ll explain about how ASIHTTPRequest works when we start to use it. But first, let’s integrate the JSON Framework while we’re at it.

Integrating JSON Framework

I already covered a lot of info about the JSON framework back in the Google Translate and JSON tutorial, so I’m not going to talk about how it works again here. However, here are the notes about how to integrate it into the project for handy reference:

  1. Download the latest version of the Open Source Objective-C JSON framework developed by Stig Brautaset.
  2. Back in FBFun, right click FBFun under “Groups & Files”, and click “Add\New Group” and name the group “JSON”.
  3. Then open the disk image of the JSON framework that you downloaded, open the JSON folder inside, and drag all of the files in that folder to the new “JSON” group you created in XCode. When the dialog pops up, verify that “Copy items into destination group’s folder (if needed)” is checked, and click “Add”.
  4. Compile your project. If it works, you’re integrated!

Integrating Pictures

We’re going to need some picture of babes and dudes to show. You can use your own, or grab these images. Once you have them downloaded, drag them into your resource group. When the dialog pops up, verify that “Copy items into destination group’s folder (if needed)” is checked, and click “Add”.

Requesting the User’s Profile

Phew! Finally, we’re ready to write some code.

The first thing we’ll need to do is figure out if you like babes, or if you like dudes. And believe it or not – you can find that out via your Facebook profile! :]

So first let’s add the headers we need and the declarations for our variables:

// Add to the top of the file
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "JSON.h"
 
// In synthesize section
@synthesize textView = _textView;
@synthesize imageView = _imageView;
@synthesize segControl = _segControl;
@synthesize webView = _webView;
@synthesize accessToken = _accessToken;
 
// In dealloc
self.textView = nil;
self.imageView = nil;
self.segControl = nil;
self.webView = nil;
self.accessToken = nil;

Nothing fancy here. Next comes the call to get the user’s Facebook profile information:

- (void)getFacebookProfile {
    NSString *urlString = [NSString 
        stringWithFormat:@"https://graph.facebook.com/me?access_token=%@", 
        [_accessToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSURL *url = [NSURL URLWithString:urlString];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDidFinishSelector:@selector(getFacebookProfileFinished:)];
 
    [request setDelegate:self];
    [request startAsynchronous];
}
 
- (void)rateTapped:(id)sender {
 
}

The first thing we do is create a string for the Graph API object that we wish to get. In this case, we want the current user’s profile, which we can access at http://graph.facebook.com/me.

However, we need to pass in the access token as well. We do this by simply appending it at the end of the URL as an HTTP get parameter. Remember we need to escape the access token with percent escapes for the URL.

Next, we send out the actual request. Instead of using NSURLRequest / NSURLConnection, we make use of ASIHTTPRequest here. This simplifies things a bit for us by managing storing the NSData for us along the way, and just giving us a callback when we’re done.

We use an override to specify the selector we want to be called when it’s finished (rather than accepting the default), this way we can have different callbacks for different requests we make. We also set ourselves as the delegate.

Notice we’re using the asynchronous method – using synchronous methods in an iPhone app is generally a no-no, as it makes the app unresponsive!

Parsing the Response from Facebook

Next add the callback for when we receive the data back from Facebook:

- (void)getFacebookProfileFinished:(ASIHTTPRequest *)request
{
    // Use when fetching text data
    NSString *responseString = [request responseString];
    NSLog(@"Got Facebook Profile: %@", responseString);
 
    NSString *likesString;
    NSMutableDictionary *responseJSON = [responseString JSONValue];   
    NSArray *interestedIn = [responseJSON objectForKey:@"interested_in"];
    if (interestedIn != nil) {
        NSString *firstInterest = [interestedIn objectAtIndex:0];
        if ([firstInterest compare:@"male"] == 0) {
            [_imageView setImage:[UIImage imageNamed:@"depp.jpg"]];
            likesString = @"dudes";
        } else if ([firstInterest compare:@"female"] == 0) {
            [_imageView setImage:[UIImage imageNamed:@"angelina.jpg"]];
            likesString = @"babes";
        }        
    } else {
        [_imageView setImage:[UIImage imageNamed:@"maltese.jpg"]];
        likesString = @"puppies";
    }
 
    NSString *username;
    NSString *firstName = [responseJSON objectForKey:@"first_name"];
    NSString *lastName = [responseJSON objectForKey:@"last_name"];
    if (firstName && lastName) {
        username = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
    } else {
        username = @"mysterious user";
    }
 
    _textView.text = [NSString stringWithFormat:
        @"Hi %@!  I noticed you like %@, so tell me if you think this pic is hot or not!",
        username, likesString];
 
    [self refresh];    
}

This method looks long, but it’s actually pretty simple.

We first convert the string we got back from the server into Objective-C objects using the JSON parser. We then look for the interested_in variable to tell if you like babes or dudes.

Based on your interest, we set the image appropriately. If it’s not there, we just set you as liking puppies (because who doesn’t like puppies?!)

Then we get your first and last name, and create a customized message for you.

One last thing: we need to modify the accessTokenFound method to start the ball rolling:

- (void)accessTokenFound:(NSString *)accessToken {
    NSLog(@"Access token found: %@", accessToken);
    self.accessToken = accessToken;
    _loginState = LoginStateLoggedIn;
    [self dismissModalViewControllerAnimated:YES];    
    [self getFacebookProfile];        
    [self refresh];
}

And that’s it! Compile and run the app, and if all works you should see something like the following:

Hot or Not Message

Where To Go From Here?

Here is a sample project with all of the code we developed in the above Facebook tutorial.

If you’re wondering what other cool stuff you can find on a user’s profile page – check out the Facebook Graph API Reference for User.

You can also get a ton of other information in a similar manner to how we got the user’s profile. With the knowledge you have here, check out the Graph API reference and see what else you can snag!

In the next Facebook tutorial in the series, we take this a step further and show you how to post to a user’s wall, upload photos, and integrate a “like button” for your Facebook fan page!

Please comment below with any comments or questions you may have… and also if you like babes or dudes. :]

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

User Comments

11 Comments

  • I am encountering problem in integrating ASSIHTTPRequest(pokeb-asi-http-request-341fb85) api....after following all those steps i am getting error for this import
    #import <GHUnitIOS/GHUnit.h>
    "No such file or directory"
    for that i included the the classes of this API
    GHUnitIOS-0.4.28
    i am able to remove some errors but in one file named ASIDataCompressorTests.m
    the declaration of NSTask giving problem i.e.NSTask undeclared...
    Am I using some old api...please suggest
    devaditya
  • devaditya wrote:
    Am I using some old api...please suggest


    Actually, it just so happens that I was implementing this same thing this weekend and discovered the same error. It seems that an update to the library has been done and it now includes some unnecessary testing files that you can remove. I deleted the "Tests" folder/group (in my project) and that seemed to clear things up for me.
    shawngrimes
  • to : shawngrimes
    yes, after i deleted the 'Test' folder , and the problem have gone away.
    it works.
    but i still have another or more problems , in the file named 'ASIWebPageRequest.h'

    //#import <libxml/HTMLparser.h>
    //#import <libxml/xmlsave.h>
    //#import <libxml/xpath.h>
    //#import <libxml/xpathInternals.h>
    these four file seemed like never founded . i delete the 'ASIWebPageRequest.h' and 'ASIWebPageRequest.m'.
    and ! the project's worked normally . so unbelievable.
    xiaonan
  • Hi Ray ,

    Thanks for this tutorial .. I have tried this tutorial. It works fine for the first Time. But get error on second time.. Error as follows:

    <Error>: DevanagariSangamMN: FT_Load_Glyph failed: error 6.
    can you please suggest, What can I do ?


    Thanks ..
    Swati
  • This code is not working anymore , please can you check this code again.
    farazhaider88
  • I have finished this tutorial and find that the JSON I get back from the API does not include an entry for interested_in?

    I then downloaded the sample project and ran that with the same result?

    I have looked at the graph api pages to see if interested_in is still applicable which of course it is......so why do I not get this back?

    It shows no errors and does bring back a chunk of my profile data?
    elpuerco63
  • I think the Facebook API tends to change from time to time, so I wouldn't be surprised if code from an older article no longer works. I haven't actually tried any of this myself but I hear plenty of developers complaining about the Facebook APIs.
    Hollance
  • Thanks Ray so much!
    pandapo
  • Hi Ray,

    Thanks for your blogs! It saves me a lot!
    I am stuck by a question a couple of days about login my app with facebook in my native iOS app.
    User can register a new account to login my app or use a existing account to login and also by facebook.
    I've created an app in facebook. I can get the authorization callback from facebook.
    But I donot know what i should next?
    After getting the facebook authorization callback. My server doesn't know whether the user is login?
    Is there any facebook api i should call or some thing else in my case? :?:

    Any suggestion will be appreciated.
    Thanks in advance.
    Alex
    alex
  • I like dudes :)

    W
    willlarche
  • as soon as i downloaded the sample project it had problems starting up
    kryptonianZ

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in May: Procedural Level Generation in Games with Kim Pedersen.

Sign Up - May

Coming up in June: WWDC Keynote - Podcasters React! with the podcasting team.

Sign Up - June

Vote For Our Next Book!

Help us choose the topic for our next book we write! (Choose up to three topics.)

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

  • Jean-Pierre Distler
  • Matt Luedke

... 55 total!

Editorial Team

  • John Clem

... 22 total!

Code Team

  • Orta Therox

... 1 total!

Translation Team

  • Jesus Guerra
  • Przemysław Rembelski
  • Wilson Lin

... 38 total!

Subject Matter Experts

  • Richard Casey

... 4 total!