Connecting your iphone app to facebook using FBconnect

Posted by: Idriss

Facebook’s engineers released an iPhone version of fbconnect few months ago. Now iphone applications are able to use the Facebook api to retrieve friends of the user, post things on the wall, etc…

We’ll see through this tutorial how to change the user status from an iphone application.

Adding facebook functionality to your native iPhone applications is surprisingly easy.  In this article, we’ll walk you through the process of adding the facebook libraries and incorporating them into your application.

1 prerequisites:

-A facebook developer account and a new empty app (To have an API key and an application secret for api calls). To create a new one, read this Facebook getting started : http://developers.facebook.com/get_started.php

-Download the FBConnect for iphone : http://github.com/facebook/facebook-iphone-sdk/

2 compile as a lib

1. The FBConnect project you downloaded is configured to create the fbconnect library. There are only a few things to do to be able to build it: change the SDK you’re compiling against and the configuration. You may want to set it to your iPhone version ( for example 3.1 ) and change the configuration to debug (Upper left combo list).

Build/Target platform options combo list

Build/Target platform options combo list

Now, control click on the target, and choose build “FBPlatform”;

But you’ll need to build one library for the simulator and one for the device. So each time you’ll need to change the lib depending if you’re testing on your device or on the simulator. To avoid that, we’ll pack all the libraries inside one using “lipo”.

First build the lib for the simulator in debug config, and then build for the device (iPhone OS) in debug mode as well.

In the Terminal, go to your project directory :

$ cd your/project

then go to the build directory, in our case src/build/

$ cd src/build

you will have 2 directories: Debug-iphonesimulator and Debug-iphoneos

each contains the compiled lib.

$ ls Debug-iphonesimulator

libFBPlatform.a

we’ll use “lipo” (man lipo) to pack the two libs in one:

$ lipo -create Debug-iphonesimulator/libFBPlatform.a Debug-iphoneos/libFBPlatform.a -output libFBPlatform-debug.a

This will create a lib with the two version of the FBPlatform so you’ll never need to change each time you switch from the simulator to the device.

Create a “lib” directory in the fbconnect-iphone directory and move the just-created lib into it.

$ mkdir ../../lib

$ mv libFBPlatform-debug.a ../../lib

you may want to repeat the process with the release version of the lib…

3 Create your project

Create a new project (cmd + shift + n), choose View-based application.

1 Basic connection code

a) connect to Facebook:

FBConnect uses it’s own controls to connect to the Facebook platform: you must use the API to create a “FaceBook Connect Button”. When the user will click on the button, a Dialog Window will appear.

To connect to facebook, in the view controller:

0 - (void)viewDidLoad {

1 session = [FBSession sessionForApplication:API_KEY

2 secret:APP_SECRET

3 delegate:self];

4 FBLoginButton* button = [[FBLoginButton alloc] init];

5 [self.view addSubview:button];

6 [button release];

6 };

<API KEY> is the “api key” you’ll find in you Facebook application settings.

<APP_SECRET> is the “application secret”. 

This will create a facebook button in the view: the user will be able to connect to Facebook by clicking on it. A dialog will appear.

Once logged in, the FBConnect module will call the function: - (void)session:(FBSession*)session didLogin:(FBUID)id; This function is defined in the protocol <FBSessionDelegate> . So if you look at line 3 of our code, we set the delegate of this call to self. So this class should implement the <FBSessionDelegate> protocol by adding this “session: didLogin:” function. This function will contain the code to execute once the user is connected.

For now we can just put a log in this function:

- (void)session:(FBSession*)session didLogin:(FBUID)uid {

NSLog(@”User %lld connected”, uid);

}

don’t forget to add that the class implements the <FBSessionDelegate> protocol in the interface:

#import <UIKit/UIKit.h>

#import “FBConnect/FBConnect.h”

@interface FBConnectExampleViewController : UIViewController <FBSessionDelegate> {

FBSession *session;

}

@end

To be able to compile we must add some more informations:

-include the libFBPlatform.a

Project>add to project (option meta a) , and then go to the fbconnect-iphone/lib directory. Choose the libFBPlatform-debug.a and click on add.

Move the added lib to the framework group or create a lib group.

-specify the headers path

on the sidebar, control click on the project root (you project name) and choose get info (meta i). Go in the “build” tab and search for “header”

in the “User header search path” add the path to the fbconnect-iphone directory which contains the FBConnect directory; usually ../fbconnect-iphone/src/

Header path

Header path


-add the FBConnect.bundle to the resources

the libFBPlatorm lib uses some resources (specially for the button), so you need to add the bundle into your project. Project>add to project (option meta a), go to the fbconnect-iphone/src and add the FBConnect.bundle file. Move it to your Resources group.

now build and run (command r)

you should see a button in the upper left corner. if you click on it, a dialog will appear requesting your username/email and password. if you correctly fill the form and click on connect, the debug console should write something like:

[Session started at 2009-11-05 11:53:24 +0800.]

2009-11-05 11:54:00.400 FBConnectExample[3463:207] User <USERID> connected

If you see that, it’s all good!

3bis Troubleshooting

i runs, but I don’t see the button:

-are you sure you imported the FBConnect.bundle?

-have you added the button to the view?

4 Calling an API Function

1 retrieve the status

We’ll not use an API call to retrieve the status of the user.

FBConnect platform API call uses, like the connection, delegates to receive the response from the Facebook Platform: When you call an api you must reference a delegate which will handle the response.

Let’s create a function retrieve the userStatus:

0 - (void)getStatus {

1 NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:

2 @"1", @"limit",

3 nil];

4 [[FBRequest requestWithDelegate:statusUpdateDelegate] call:@”facebook.Status.get” params:params];

5 }

The parameters of the API call must be in a dictionary. Here we just specify the amount of statuses we want to retrieve.

on line 4, like the connection, we set the delegate for the request. Like previously, we can set the view controller be this Delegate (have to implement the FBRequestDelegate protocol), but if you have several api calls, the same response function will be called…

An elegant solution is to create one delegate object for each api call.

Let’s then create the StatusUpdateDelegate (command n, new objective c class). This class must implement the FBRequestDelegate protocol:

#import <Foundation/Foundation.h>

#import “FBConnect/FBConnect.h”

@interface StatusUpdateDelegate : NSObject <FBRequestDelegate> {

NSString *message;

}

The 2 main functions that we are interested in are:

- (void)request:(FBRequest*)request didLoad:(id)result;

- (void)request:(FBRequest*)request didFailWithError:(NSError*)error;

The “didLoad” function is call when the results are ready to be processed.

For now we just want to Log the status:

0 - (void)request:(FBRequest*)request didLoad:(id)result {

1      NSArray* statuses = result;

2 NSDictionary* status = [statuses objectAtIndex:0];

3 message = [status objectForKey:@"message"];

4 NSLog(@”status : %@”, message);

5 }

The result comes in an array containing dictionaries. For more informations try to log directly the array.

Now instanciate this class in our view controller:

in the viewDidLoad method:

statusUpdateDelegate = [[StatusUpdateDelegate alloc] init];

Where statusUpdateDelegate is a member field of the view controller.

Now let’s call the status request function and we’ll be fine:

in the view controller:

- (void)session:(FBSession*)session didLogin:(FBUID)uid {

NSLog(@”User %lld connected”, uid);

[self getStatus];

}

TO recap we have the following code:

ViewController.m:

- (void)viewDidLoad {

[super viewDidLoad];

session = [FBSession sessionForApplication:API_KEY

secret:APP_SECRET

delegate:self];

FBLoginButton* button = [[FBLoginButton alloc] init];

[self.view addSubview:button];

[button release];

statusUpdateDelegate = [[StatusUpdateDelegate alloc] init];

}

- (void)viewDidUnload {

[statusUpdateDelegate dealloc];

}

- (void)session:(FBSession*)session didLogin:(FBUID)uid {

NSLog(@”User %lld connected”, uid);

[self getStatus];

}

- (void)getStatus {

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:

@"1", @"limit",

nil];

[[FBRequest requestWithDelegate:statusUpdateDelegate] call:@”facebook.Status.get” params:params];

}

- (void)dealloc {

[session.delegates removeObject:self];

[super dealloc];

}

StatusUpdateDelegate.m:

- (void)request:(FBRequest*)request didLoad:(id)result {

NSArray* statuses = result;

NSDictionary* status = [statuses objectAtIndex:0];

message = [status objectForKey:@"message"];

NSLog(@”status : %@”, message);

}

- (void)request:(FBRequest*)request didFailWithError:(NSError*)error {

NSLog(@”ERROR on status update: %@”, error);

}

Build and run (command r), connect, and after a while the status message should appear in the debug console.

5 Post a new status

now we’ll post the new user status.

But to do that, we need extended rights…

To obtains those rights, the user must allow it via a Facebook platform dialog.

To simplify the process, we’ll display the dialog when the user successfully logged in; so in the view controller, function session:didlogin :

0 – (void)session:(FBSession*)session didLogin:(FBUID)uid {

1 NSLog(@”User %lld connected”, uid);

2 FBPermissionDialog* dialog = [[FBPermissionDialog alloc] init];

3 dialog.delegate = self;

4 dialog.permission = @”status_update”;

5 [dialog show];

6 [dialog release];

7 [self getStatus];

8 }

The code to add is between line 2 and 6.

The permission dialog works like the session and api call: it needs a delegate. To keep it simple we’ll say that the delegate is the view controller (this class must now implement the FBDialogDelegate), and we’ll add the function “dialogDidSucceed”:

- (void)dialogDidSucceed:(FBDialog*)dialog {

NSLog(@”Extended rights approved”);

}

Note that we ask for specific rights on line 4; each different actions needs different rights (The API documentation explains this).

Now that we have extended rights on the status update, we can post a new status by using an API call:

-(void)setStatus:(NSString *)status {

NSString *statusString = status;

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:

statusString, @"status",

@"true", @"status_includes_verb",

nil];

[[FBRequest requestWithDelegate:setStatusDelegate] call:@”facebook.Users.setStatus” params:params];

}

No fancy stuff here, same as before: setStatusDelegate is a delegate class which implements FBRequestDelegate protocol.

6 Comments

Facebook Connect for iphone is simple to use: you can add very quickly a social aspect to your application. Now it’s up to you to imagine an awesome application.

Here’s a small project using what we saw here: Facebook Example

The example project screenshot

The example project screenshot

14 Responses So Far... Leave a Reply:

  1. Vibhor Goyal says:

    Great tutorial!!! Didn’t work for me though, when I compile, it says build completed successfully, but libFBPlatform.a is never created. FBConnect for iphone is getting really frustrating for me.

  2. Idriss says:

    Hi!
    Is it when you’re working with the Facebook connect project?
    Depending on the active SDK (upper left combo list) the libFBPlaform.a will be located in different subdirectories of the build directory (Debug-iphonesimulator for the debug simulator, Debug-iphoneos for the iphone device, etc…).
    The debug version of the libFBPlatform is provided in the example project, if you have some problem you can include this one.
    Do not forget to add it to your project.

  3. Arun says:

    Follow every steps perfectly. Nice Tutorial, But still not get Connected with FaceBook.
    I\When i Build Application, it Shows with 21 Errors, mainly FBConnect/FBConnect.h no such files or Directory found.

    Still need your Help. kindly Guide me for this.

    Looking forwards,

    Regards,
    Arun Thakkar

  4. Idriss says:

    Hi Arun!
    Did you put the correct path to the facebooklib header files? Should be “../fbconnectlib-iphone/src” but it depends on your project setup. Which path did you put?

  5. Jesse says:

    Great write up on building a 3rd party lib and adding to a project. Thanks!

  6. David says:

    Thanks, Works Great… Just a quick question though. Is there an easy way (or built in mechanism) to detect IF a user is logged in (so if they try to update the status and they are not i can prompt them to log in)

  7. Idriss says:

    Thanks!
    Yes there is a way to do that: use the FBSession method
    -(BOOL)resume
    It uses the data cached on the disk to open the session. After you create your session, call [session resume]. It will return TRUE if it managed to re-open the session, and FALSE if the user have to re-enter his information.

  8. Idriss says:

    Thanks!
    I’ll try to write that asap!

  9. Zeeeshan Khan says:

    Hi,

    I am getting so many error message whenever i try to compile your project.
    I have downloaded some other facebook sample projects for iPhone but all are giving the same error.
    I have also tried myself after watching this video http://vimeo.com/3616452 but still getting same error messages.
    I have added the path the the “Header Search Paths” as ../../fbconnect-iphone/src. But still getting same error.

    Please help me to come up from this error.

    Errors:

    “error: FBConnect/FBSession.h: No such file or directory”
    “error: FBConnect/FBRequest.h: No such file or directory”
    “error: FBConnect/FBLoginButton.h: No such file or directory”
    “error: FBConnect/FBLoginDialog.h: No such file or directory”
    “error: FBConnect/FBPermissionDialog.h: No such file or directory”
    “error: FBConnect/FBFeedDialog.h: No such file or directory”

    Please help me.

    Thanks in advance,
    Zeeshan Khan

  10. Idriss says:

    Hi Zeeshan,

    This message error appears when the path to the facebook headers is wrong. Check the path where you put your facebook sources.

    If you still have some troubles, switch to a cross referenced project in XCode. I’ll right a tutorial about that in a couple of days.

  11. tilluigi says:

    hi,

    thanks for putting this up! the video “setting up fb in five minutes” (http://vimeo.com/3616452) made me think its a snap, but its actually a lot more complicated!

    i got it all set up properly. basically it compiles, but as soon as i try to add the button i get the following error:

    Undefined symbols:
    “.objc_class_name_FBLoginButton”, referenced from:
    literal-pointer@__OBJC@__cls_refs@FBLoginButton in MenuLayer.o
    “.objc_class_name_FBSession”, referenced from:
    literal-pointer@__OBJC@__cls_refs@FBSession in MenuLayer.o
    ld: symbol(s) not found

    collect2: ld returned 1 exit status

    i do have the bundle in place, any idea?

  12. Idriss says:

    Hi Tilluigi!
    This happens when the lig is not linked with the binary.
    Check in your target, in the little grey folder named “link binary with libraries” you should have a reference to the FBConnect library. If not, this is your problem:
    (From step 3)
    -include the libFBPlatform.a
    Project>add to project (option meta a) , and then go to the fbconnect-iphone/lib directory. Choose the libFBPlatform-debug.a and click on add.
    Move the added lib to the framework group or create a lib group.

    It should work fine after that.

  13. Sami says:

    Hi,

    How can I keep the session on so that I do not have to log into Facebook every time I open my iPhone application?

    Cheers,

    Sami

  14. Idriss says:

    Hello Sami!
    David had the same question in the comments. It’s easy to to: after creating the session, use the FBSession method
    -(BOOL)resume
    it will return true if the user session is in cache.