Facebook Tutorial for iOS: How To Post to a User’s Wall, Upload Photos, and Add a Like Button from your iPhone App

Ray Wenderlich
I have a soft spot for malteses!

I have a soft spot for malteses!

This article is the final 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 the second part of the series, we covered how to get information from Facebook using the Graph API, in particular the user’s profile.

In this article, we’ll cover how to post to the user’s wall, how to upload a photo to their photo album, and even how to add a “like” button to your Facebook fan page.

So let’s rate some babe, dudes… and maybe a puppy or two!

Posting the Photo

When the user clicks the Rate button, we want our app to upload the photo to Facebook along with a little message that says if the user thought it was hot or not.

So replace rateTapped with the following:

- (void)rateTapped:(id)sender {
 
    NSString *likeString;
    NSString *filePath = nil;
    if (_imageView.image == [UIImage imageNamed:@"angelina.jpg"]) {
        filePath = [[NSBundle mainBundle] pathForResource:@"angelina" ofType:@"jpg"];
        likeString = @"babe";
    } else if (_imageView.image == [UIImage imageNamed:@"depp.jpg"]) {
        filePath = [[NSBundle mainBundle] pathForResource:@"depp" ofType:@"jpg"];
        likeString = @"dude";
    } else if (_imageView.image == [UIImage imageNamed:@"maltese.jpg"]) {
        filePath = [[NSBundle mainBundle] pathForResource:@"maltese" ofType:@"jpg"];
        likeString = @"puppy";
    }
    if (filePath == nil) return;
 
    NSString *adjectiveString;
    if (_segControl.selectedSegmentIndex == 0) {
        adjectiveString = @"cute";
    } else {
        adjectiveString = @"ugly";
    }
 
    NSString *message = [NSString stringWithFormat:@"I think this is a %@ %@!", adjectiveString, likeString];
 
    NSURL *url = [NSURL URLWithString:@"https://graph.facebook.com/me/photos"];
    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request addFile:filePath forKey:@"file"];
    [request setPostValue:message forKey:@"message"];
    [request setPostValue:_accessToken forKey:@"access_token"];
    [request setDidFinishSelector:@selector(sendToPhotosFinished:)];
 
    [request setDelegate:self];
    [request startAsynchronous];
 
}

In the beginning, we check what image the user is looking at, and get the path of the image to send appropriately. We also get a string describing the image that we’ll use a bit later.

Next, we create a string that we’ll use as a caption for the photo, taking whether the segmented control is on “hot” or “not” and the image currently shown.

The real meat of the work is again done with ASIHTTPRequest – or wait a minute, ASIFormDataRequest. ASIFormDataRequest is a subclass of ASIHTTPRequest, that makes it easy to POST data to a web server – which is exactly what we need to do to upload a photo.

To see what types of things you can post to Facebook, check out the Graph API reference, in particular the “Publishing to Facebook” section. There we can see that when uploading a photo, we can include just two things: the photo itself and the caption (called “message” here).

ASIFormDataRequest has many ways to include raw data in a form request. We’re using the addFile method to include the image that way. If you need to include data from NSData or another method, check out the handy ASIHTTPRequest docs to see other ways to include your data.

So, after we set the image, message, and access token, we fire off the request and set a delegate to be called back when it’s done. And in that, let’s get some info on the photo!

Getting Object Information

After we post a new object to Facebook, Facebook returns to us the ID. We can use that ID to query the object, and get other potentially useful information – like the link to the photo on Facebook in this case!

So let’s give that a shot. Add this method next:

- (void)sendToPhotosFinished:(ASIHTTPRequest *)request
{
    // Use when fetching text data
    NSString *responseString = [request responseString];
 
    NSMutableDictionary *responseJSON = [responseString JSONValue];
    NSString *photoId = [responseJSON objectForKey:@"id"];
    NSLog(@"Photo id is: %@", photoId);
 
    NSString *urlString = [NSString stringWithFormat:
        @"https://graph.facebook.com/%@?access_token=%@", photoId, 
        [_accessToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSURL *url = [NSURL URLWithString:urlString];
    ASIHTTPRequest *newRequest = [ASIHTTPRequest requestWithURL:url];
    [newRequest setDidFinishSelector:@selector(getFacebookPhotoFinished:)];
 
    [newRequest setDelegate:self];
    [newRequest startAsynchronous];
 
}

Here we pull out the photo ID after a sucessful upload. Based on that, we send out another request to get the properties of that object with the URL https://graph.facebook.com/objectID. IDs are unique across all types of objects, so this would work for any object type.

We send out the request the exact same way we did when we queried for the user’s profile in the last Facebook tutorial. When it’s done, we’ll get a callback on getFacebookPhotoFinished, so let’s add that next!

Posting to the User’s Wall

Once we get the photo info, we can pull out the link to the photo and potentially do something useful with it. My original idea was to include the image in a post on the user’s wall saying what he rated the photo, but apparantly Facebook doesn’t allow you to link to photos on its network on wall posts for whatever reason.

Update: Strike that! Mic Pringle from the comments section pointed out that Facebook now allows you to post links to pictures in its stream on wall posts, so we’re good to go!

So add this to the file next:

- (void)getFacebookPhotoFinished:(ASIHTTPRequest *)request
{
    NSString *responseString = [request responseString];
    NSLog(@"Got Facebook Photo: %@", responseString);
 
    NSMutableDictionary *responseJSON = [responseString JSONValue];   
 
    NSString *link = [responseJSON objectForKey:@"link"];
    if (link == nil) return;   
    NSLog(@"Link to photo: %@", link);
 
    NSURL *url = [NSURL URLWithString:@"https://graph.facebook.com/me/feed"];
    ASIFormDataRequest *newRequest = [ASIFormDataRequest requestWithURL:url];
    [newRequest setPostValue:@"I'm learning how to post to Facebook from an iPhone app!" forKey:@"message"];
    [newRequest setPostValue:@"Check out the tutorial!" forKey:@"name"];
    [newRequest setPostValue:@"This tutorial shows you how to post to Facebook using the new Open Graph API." forKey:@"caption"];
    [newRequest setPostValue:@"From Ray Wenderlich's blog - an blog about iPhone and iOS development." forKey:@"description"];
    [newRequest setPostValue:@"http://www.raywenderlich.com" forKey:@"link"];
    [newRequest setPostValue:link forKey:@"picture"];
    [newRequest setPostValue:_accessToken forKey:@"access_token"];
    [newRequest setDidFinishSelector:@selector(postToWallFinished:)];
 
    [newRequest setDelegate:self];
    [newRequest startAsynchronous];
 
}

If you’ve done the Facebook Connect tutorial or used Facebook Connect before, the above should look pretty similar. We’re setting the same kinds of values we normally would on a wall post here – message, name, caption, etc. – except it is a lot nicer to use this way I think.

Now that you’ve seen how to upload photos, you’ll see that there’s really nothing different about making wall posts! You’re just setting different parameters, which you can find out about in the Graph API reference.

One last callback to add:

- (void)postToWallFinished:(ASIHTTPRequest *)request
{
    NSString *responseString = [request responseString];
 
    NSMutableDictionary *responseJSON = [responseString JSONValue];
    NSString *postId = [responseJSON objectForKey:@"id"];
    NSLog(@"Post id is: %@", postId);
 
    UIAlertView *av = [[[UIAlertView alloc] 
            initWithTitle:@"Sucessfully posted to photos & wall!" 
            message:@"Check out your Facebook to see!"
            delegate:nil 
            cancelButtonTitle:@"OK"
            otherButtonTitles:nil] autorelease];
	[av show];
 
}

We just pop up a dialog here to let the user know when we’re done.

That’s it! Run the project and you shoudl see a success message when you click Rate:

Success Dialog

And then a post (or two, one is automatically made the first time you upload a new photo album I think) to your wall:

Our Wall Post and Photo Upload

Adding a Like Button to your Facebook Fan Page

One last thing to discuss. These days as app developers, a lot of us are trying to start up Facebook Fan Pages, so maybe we want to add a like button to our apps!

After learning about the Graph API you might start looking for some kind of ability to POST to the user’s likes somewhere. That would make a lot of sense, wouldn’t it? But unfortunately, Facebook has decided not to allow custom like buttons.

However, luckily that doesn’t mean we can’t use like buttons in our apps – we just have to use Facebook’s like button. And to do that, we have to embed it in a webview in our app. And we have one standing by just for that!

All you have to do is visit Facebook’s Like Box Maker and fill out the values to create the Like button for your Facebook Fan page the way you like it. For the space we’ve given it in this Facebook tutorial, you should set connections to 0 and stream and header off.

Then add the following method above getFacebookProfile, replacing the likeButtonIframe with your own likebox code (don’t forget to escape out the quotes):

- (void)showLikeButton {    
    NSString *likeButtonIframe = @"<iframe src="http://www.facebook.com/plugins/likebox.php?id=122723294429312&amp;width=292&amp;connections=0&amp;stream=false&amp;header=false&amp;height=62" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:282px; height:62px;" allowTransparency="true"></iframe>";
    NSString *likeButtonHtml = [NSString stringWithFormat:@"<HTML><BODY>%@</BODY></HTML>", likeButtonIframe];    
    [_webView loadHTMLString:likeButtonHtml baseURL:[NSURL URLWithString:@""]];    
}

Then just add this at the end of accessTokenFound:

[self showLikeButton];

And if all works well, your like button should appear in the window!

Facebook Fan Page Like Button in our iPhone App

Where To Go From Here?

Here is a sample project with all of the code we’ve developed in this Facebook tutorial series.

At this point, you should be ready to use Facebook’s Graph API for whatever you need – without having to wait for an update to Facebook Connect! I’d love to hear what you guys plan on using it for.

And while we’re on the topic of Facebook, if you enjoyed this Facebook tutorial I’d love it if you would “like” my own Facebook fan page! Just click the link below (or in the app)! :]

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

81 Comments

[ 1 , 2 , 3 , 4 , 5 , 6 ]
  • Hi,

    I open a fullpage WebView in my ios app and load some html content that has a Fb like button. The button is loaded via the standard http://developers.facebook.com/docs/ref ... /like-box/ and I use the 'url' option.

    Clicking the link opens a FB login page as expected. Entering login info and clicking 'login' results in a fullpage white screen. Exiting the app and re-entering still shows this white screen.

    I get the same results testing in the emulator (on ios 5 and 6) and on my iphone 4 (running ios 6).

    Doing the same using the code in my webview in a browser works ok.

    I am guessing there is some authentication issue here in that facebook doesn't know how to return to the calling page in my webview?

    Many thanks for your help
    J
    jscolton
  • error ocurred: ld: library not found for -lz.1.2.3
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    I am not able even to compile it :(
    gneil90
  • linker command failed with exit code 1 (use -v to see invocation) that was my issue
    kryptonianZ
  • gneil90 wrote:error ocurred: ld: library not found for -lz.1.2.3
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    I am not able even to compile it :(

    In the Project Settings screen in Xcode, under Linked Frameworks and Libraries, remove libz.1.2.3.dylib and replace it with libz.1.2.5.dylib (or just libz.dylib).
    Hollance
  • Ray,

    First of all Thank you for your valuable time spending with us.i used your facebook tutorial for my new project for posting to wall.Unfortunately my app posting two post to feed .
    1.one feed has an image and caption.(Its that i want).
    2.A small image of above,caption,message and a link.(when we click on that link it leads to same image on right(small image)).
    i am new to this,please help with this.
    fahadios
  • Screen Shot 2013-12-12 at 12.04.19 pm.png
    Ray,

    First of all Thank you for your valuable time spending with us.i used your facebook tutorial for my new project for posting to wall.Unfortunately my app posting two post to feed .
    1.one feed has an image and caption.(Its that i want).
    2.A small image of above,caption,message and a link.(when we click on that link it leads to same image on right(small image)).
    i am new to this,please help with this.
    fahadios
[ 1 , 2 , 3 , 4 , 5 , 6 ]

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!

Our Books

Our Team

Tutorial Team

... 50 total!

Update Team

  • Ray Fix

... 15 total!

Editorial Team

... 23 total!

Code Team

  • Orta Therox

... 3 total!

Translation Team

  • Sungwook Yeom
  • Zihan Xu
  • Jesus Guerra

... 33 total!

Subject Matter Experts

  • Richard Casey

... 4 total!