Saturday, July 24, 2010

Sharing to Facebook from an iPhone App

First, let me say that the sample code provided by Facebook and others is teh suck. Some of the top hits when you search for stuff are broken samples. Be careful out there!

Second, the documentation itself is crap.

So I'm here to go over the flow that I used to share to facebook. If you're developing an iPhone app and want a "Share on facebook!" sort of thing, then start by perusing the readme: http://wiki.developers.facebook.com/index.php/Facebook_iPhone_SDK That's nice and all, but it's not shippable.

Background #1: Facebook updates. The 'stories' that appear on your wall, and are shared to your friends' home pages, are all little text doodads with links to content stored elsewhere. Adding a story to a user's wall is the simplest thing, and it's what most of those Facebook games do. There are status updates and then there are other stories; a status update is what happens when you don't include an actionable item (a 'call to action' type link). Mostly you just pull some key/value pairs together (see Facebook's list of attachments) then make a request.

Background #2: You can't upload images to a wall, only to your photo album, for example. Developers making utilities, games, and entertainment want to add a story that contains a custom image. You might note that most facebook games don't do that; they use a generic image instead, like a picture of a cow or sheep or barn as FarmVille does. Uploading a custom image is tricky. If you want a wall story with a custom picture, you have to either (a) first upload the image to the user's photo album (the default one has a limit of 500 photos, one dedicated to your app will have a 1000-photo limit), which means that two stories will appear back-to-back on the user's wall, or (b) store the image somewhere else instead and link to that.

What you wanna do:
0) First, allow the Facebook Developer application. Go to http://www.facebook.com/developers and 'Allow' it.
1) Create an application (see the image on the right). Yes, you might need to make your application page pretty.
2) Go to XCode. Create your own facebook helper class. I called mine FacebookHelper, cuz I'm creative like that. The point of creating this class is to not mix facebook delegates and dialog handlers and all that crap into your other classes. Posting isn't just one function call (there can be three or more callbacks involved), so partitioning it all into a separate class will help.
3) Add an entry point to this class. I haven't yet refactored this out; right now, I copy-n-paste the class into a new project and edit the implementation. So my entry point isn't
- (void) Share:(NSString*)shareText;
blah blah blah, but just
- (void) Share;
4) That entry point will look roughly like this:
{
if (self.session==nil || !self.session.isConnected)
 [self ShowLogin];
else if (!havePermission)
 [self AskPermission];
else
 [self PostToWall];
}
5) Write the FB login code and delegates. This means creating an FBLoginDialog and show'ing it.
6) If you need extended permissions of any type, create & show an FBPermissionDialog. Note that your FBDialog delegate callbacks will need to differentiate the type of dialog shown. I did this by sticking an enum in the dialog's "tag" field, and switching on it in the dialog:didFailWithError, dialogDidSucceed:, and dialogDidCancel: callbacks.
7) Finally, post to the wall. Do this by creating an FBStreamDialog, add an attachment string with all your parameters, like so:
 "name":"My App Name","message":"User enters this text, this is placeholder","caption":"etc"
These key-value pairs will include a link to your app and a link to the image to use in the post.
7b) If you're uploading an image to one of the user's albums, you use an FBRequest instead of showing an FBStreamDialog.
{
 NSMutableDictionary* args = [[[NSMutableDictionary alloc]init]autorelease];
 [args setObject:@"my caption" forKey:@"caption"];
 FBRequest* request = [FBRequest requestWithDelegate:self];
 [request call:@"photos.upload" params:args dataParam:image];
}

Later on I'll upload the entirety of the class so that you can see it all in process. Plus I'll probably clean this post up, too... meanwhile, I've got to run.

1 comment:

Qwiki said...

you write gr8.
if you'll present your latest code it'll be be very helpful and appreciated.

Thanks