Adding a Facebook “Like” button to an iPhone application.

I, like many other iPhone app developers, have spent a long time wishing that there was a way to add a simple like button to my iPhone applications. I recently decided it was time for this to happen. After a solid day of pulling out my hair, I can at last declare victory. Here is what I did:

Update: Sorry, this no longer works after Facebook has made some changes to their API. If anyone has a new way to do this, please let me know.

– This guide assumes you already have the FB Connect API integrated into your application and you have an existing application

First, you need to make a few changes to the FB Connect API:

1- Subclass the existing FBLoginDialog as so:

//LikeFBLoginDialog.h
#import
#import "FBLoginDialog.h"
@interface LikeFBLoginDialog : FBLoginDialog {
}
@end
 
//LikeFBLoginDialog.m
#import "LikeFBLoginDialog.h"
@implementation LikeFBLoginDialog
 
// overridden to check against our *own* URLs
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
 NSURL* url = request.URL;
 NSRange range = [[url absoluteString] rangeOfString:@"login"];
 if (range.length <= 0) {
    [self dialogDidSucceed:url];
    return NO;
 }else {
    NSLog(@"Loading");
    return YES;
 }
}
@end

2- Remove some error handling from FBDialog.m that stops our button from working comment out the lines you see commented out below.

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
  // 102 == WebKitErrorFrameLoadInterruptedByPolicyChange
 
  if (!([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102)) {
    //[self dismissWithError:error animated:YES];
  }
}

3- Create a FB manager class to manage your facebook connect objects

//MyFBManagerDelegate.h
#import "FBDialog.h"
@protocol MyFBManagerDelegate<NSObject,NSCoding>
@optional
-(void) dialogDidSucceed:(FBDialog*)dialog;
@end
 
//MyFBManager.h
#import
#import "FBConnect/FBConnect.h"
#import "MyFBManagerDelegate.h"
#define kAppKey                @"yourFBkey"
#define kAppSecret            @"yourFBsecretkey"
@interface MyFBManager : NSObject {
 FBSession * session;
 id delegate;
 NSDictionary * likeWebViews;    //keys are URL values are webviews
 FBLoginDialog * loginDialog;
}
-(UIView *) newLikeView:(NSString*)likeUrl width:(float) width x:(float)x y:(float)y;
-(void) showLogin;
@property(nonatomic,retain) FBLoginDialog * loginDialog;
@property(nonatomic,retain) NSDictionary * likeWebViews;
@property(nonatomic,retain) UIViewController * delegate;
@property(nonatomic,retain) FBSession * session;
@end
 
//MyFBManager.m
#import "MyFBManager.h"
#import "LikeFBLoginDialog.h"
@implementation MyFBManager
@synthesize session;
@synthesize likeWebViews;
@synthesize delegate;
@synthesize loginDialog;
-(id) init {
  self = [super init];
  if ( self ) {
     session = [[FBSession sessionForApplication:kAppKey secret:kAppSecret delegate:self] retain];
     [session resume];
     likeWebViews = [[NSMutableDictionary alloc] init];
  }
  return self;
}
 
//this is a helper method for this class that will show the login dialog if needed
-(void) showLogin {
  if(![session isConnected]) {
     if(loginDialog != nil){
        [loginDialog release];
        loginDialog = nil;
     }
     loginDialog = [[FBLoginDialog alloc] initWithSession:session] ;
     [loginDialog show];
   }
  else { }
}
 
//this function should be called to render the buttons, which are returned as UIWebView.
//Unfornatetly, after the first time the like URL is loaded, it resizes it and does crazy things.
//So everytime we want to re-render this button, we need to call this to create an entirely object for it.
//these are stored in a dictionary so multiple like URLS can be managed
-(UIView *) newLikeView:(NSString*)likeUrl width:(float) width x:(float)x y:(float)y;
{
  UIWebView * webView = [likeWebViews objectForKey:likeUrl];
  if(webView != nil) {
     [webView removeFromSuperview];
     [webView release];
     webView = nil;
  }
  webView = [[[UIWebView alloc] initWithFrame:CGRectMake(x, y, width, 35)] retain];
  NSString *likeFacebookUrl = [NSString stringWithFormat:@"%@%@&show_faces=false&width=225&height=20& layout=button_count",@"http://www.facebook.com/plugins/like.php?href=",likeUrl];
  [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:likeFacebookUrl]]];
  webView.opaque = NO;
  webView.backgroundColor = [UIColor clearColor];
  webView.delegate = self;
  [self.likeWebViews setValue:webView forKey:likeUrl];
  return webView;
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark UIWebViewDelegate
//this method will intercept any requests from the like button to the facebook login page and pop up a log in dialog instead.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
  NSRange range = [[[request URL] absoluteString] rangeOfString:@"login.php"];
  if (range.length > 0) {
     if(loginDialog != nil){
        [loginDialog release];
     }
     loginDialog = [[LikeFBLoginDialog alloc] init];
     [loginDialog loadURL:[[request URL] absoluteString] method:@"GET" get:nil post:nil];
     loginDialog.delegate = self;
     [loginDialog show];
     return NO;
  }
  NSLog([[request URL] absoluteString]);
 
  return YES;
}
 
//after we are logged in, call the delegate method. The delegate method should re call the newLikeView to re-render the like button
-(void)dialogDidSucceed:(FBDialog*)dialog{
  if(delegate != nil &&; [delegate respondsToSelector:@selector( dialogDidSucceed:)]) {
     [delegate dialogDidSucceed:dialog];
  }
}
 
-(void) dealloc
{
[super dealloc];
[loginDialog release];
[likeWebViews release];
[likeWebView release];
[session release];
[delegate release];
}
@end

4- Now, in you need to make sure your appDelegate contain a MyFBManager and initialize it in the AppDidFinishLoad method

//YourAppDelegate.h
#import "MyFBManager.h"
@class Common;
@interface YourAppDelegate : NSObject  {
    ....
   <strong>MyFBManager * fbManager;</strong>
}
@property(nonatomic,retain) MyFBManager * fbManager;
.....
 
//YourAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	fbManager = [[MyFBManager alloc] init];
       ...

5- You are ready to use the like button. In the view controller of the class you want to add the like button to, make sure you implement the MyFBManager protocol and add the following code

//this will re-render the like button after the user logs in
-(void)dialogDidSucceed:(FBDialog*)dialog{
  YourAppDelegate * dg = (YourAppDelegate*)[UIApplication sharedApplication].delegate;
  NSString *likePage = @"http://google.com";
  [self.view addSubview:[dg.fbManager newLikeView:likePage width:270 x:0 y:0]];
}
 
//the like button should be re-rendered each time the view appears in case your facebook login status has //changed. For example if you had a settings screen that allowed you to log out or log in, re-rendering it makes it //work okay.
-(void)viewWillAppear:(BOOL)animated
{
  YourAppDelegate * dg = (YourAppDelegate*)[UIApplication sharedApplication].delegate;
  NSString *likePage = @"http://google.com";
  dg.fbManager.delegate = self;
  [self.view addSubview:[dg.fbManager newLikeView:likePage width:270 x:0 y:0]];
}

BOOM! Like buttons. You’re welcome

  • http://genericwpthemes.com WP Themes

    Good post and this post helped me alot in my college assignement. Say thank you you as your information.

  • sl4ter

    you should provide example source code

  • http://www.NowBranded.com Logan Sease

    all the source code you need has been provided….

  • http://www.ngdevices.com/media-internet-tablet-new-generations-devices tablet

    I owned an iPhone 3GS and it truly does wonder. I like it from the icons to how the transition works. Thinking of changing to iPhone 4 quickly soon after my next month’s wage.

  • http://moredecisive.com Steve Steinitz

    Hi Logan,

    Thanks for sharing your good work.

    I’ve implemented the above but am having trouble getting the Like button to appear. In my viewController.viewDidLoad I’m doing:

    [self.view addSubview: [appDelegate.fbManager newLikeView: likePage width: 270 x: 0 y: 0]];

    Is that the right idea? It seems to create a view but i don’t see anything.

    Thanks again,

    Steve

  • http://moredecisive.com Steve Steinitz

    27 Oct 10
    Hi again Logan,

    I solved the problem. There were actually two problems:

    1. UIViewController.viewWillAppear doesn’t get called for all views. Stackoverflow and other sites discussions that.

    2. MyFBManager.newLikeView has a subtle error where it creates the likeFacebookUrl: there is a stray space before layout=button_count. The url seems to work when pasted into a web browser but not when running from the iPhone. At least that’s how it seemed to me in a flurry of debugging. Anyway, removing the space made things work.

    There were also some other minor artefacts from the process of copying the source code from the web into Xcode.

    All in all though, the code is ready for prime time.

    A tip for others: create a simple webview first, perhaps like this:

    UIWebView * webView = [[[UIWebView alloc] initWithFrame:CGRectMake
    (50, 220, 225, 35)] retain];
    NSString *l ikeFacebookUrl = @”http://www.facebook.com/plugins/like.php”;
    [webView loadRequest: [NSURLRequest requestWithURL:
    [NSURL URLWithString: likeFacebookUrl]]];
    [self.view addSubview: webView];

    in viewDidLoad or similar and confirm that the like button shows up. (Remember, for some views loadView, viewWillLoad and viewWillAppear never run.) Then, when you get that working, try calling Logan’s code.

    Thanks again Logan for your generous and helpful share.

    Steve

  • http://www.gomobile.no Espen B

    Hi,

    I was wondering how I can keep the session from the initial Facebook Log in through the FBConnect? Is there some way to bring that session into the new web view? I experience that I have to log in again in the other web views I create with your code.

    Thanks for any help or pointers you could give me :-)

    Cheers,
    Espen

  • Chris

    Hey Logan,

    great work.

    Could you please tell me, which version of the FB iOS SDK you used in this example?
    In newer versions there is no FBSession – in older ones no FBLoginDialog …

    Thank You
    Chris

  • M:ke

    This tip and all of the same kind dont work for me. This example hangs with “Loading” in Debug output. If I incomment the lines (in FBDialog.m):

    if (!([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102)) {
    //[self dismissWithError:error animated:YES];
    //NSLog(@”error: %@”, [error description]);
    }

    I get:
    error: Error Domain=NSURLErrorDomain Code=-999 “The operation couldn’t be completed. (NSURLErrorDomain error -999.)” UserInfo=0x5f49b90 {NSErrorFailingURLKey=https://ssl.facebook.com/login.php?api_key=xxx&skip_api_login=1&display=popup&nux=1&referer&social_plugin=like&external_page_url=http%3A%2F%2Fgoogle.com&next=http%3A%2F%2Fwww.facebook.com%2Fconnect%2Fuiserver.php%3Fmethod%3Dopt.inlike%26app_id%xxx%26display%3Dpopup%26nux%3D1%26referer%26social_plugin%3Dlike%26external_page_url%3Dhttp%253A%252F%252Fgoogle.com%26%252Aapp_id%252A%xxx%26from_login%3D1

    When I copy this link into my browser, I receive the permissions dialog, but in my application, no session were initialized and no uiwebview is able to read my like status.
    Here is my test project: http://rapidshare.com/files/433433798/FacebookLike.zip with the old FBConnect API included. Dont forget to insert YOUR App Key and Secret in MyFBManager.h.
    And to change the “header search path” to FBConnect directory path.

  • Nitesh

    Hey i am getting an Like it Button after that i get login after putting my credentials when i press “Login” i am getting an error Like this

    2010-12-18 22:55:08.488 FBTest[2101:307] -[LikeFBLoginDialog loadURL:method:get:post:]: unrecognized selector sent to instance 0x16af50
    2010-12-18 22:55:08.490 FBTest[2101:307] *** WebKit discarded an uncaught exception in the webView:decidePolicyForNavigationAction:request:frame:decisionListener: delegate: -[LikeFBLoginDialog loadURL:method:get:post:]: unrecognized selector sent to instance 0x16af50

    Can any one help me out to resolve this or please some more clear steps for implementing this ???

    Thanks a lot in advance…

  • saleel

    Hi
    I am New to iphone development so i am not getting the exact file structure you mentioned here.
    Can You elaborate on that? and which files in fbconnect we need to change??

    Thanks

  • Abdullah Waseer

    any one who has the source code please post it at abdullah.waseer@gmail.com i am experiencing a problem that when i hit the like button the dialog box is showing up but the webView is not loading the faceBook login page. its showing only activity indicator.

  • Coding behind button?

    I may do to use this API behind button to like my app of facebook, what coding is required to be done behind a buttonpressed event?

  • Oren

    Hi,

    I am new to iphone development and I don’t know why but the debugger stuck on
    this line… – dg.fbManager.delegate = self;

    can anyone help me with that?

    Thanks

  • harish.boyin

    Hi,

    I am new to this iphone. I am using the facebook api in this application. I am having a small query please clarify. If the user is searching one of the product in the iphone and there is a option to connect the facebook. If the user clicks the option i will go to the facebook login page then the user enters his information then clicking the submit button of the login page i will go to the product information page in the facebook. The user name will add in the product contact list information. For that one we will use any API??

    Please help me this one

    Thanks In Advance

  • tamanna

    Hello,

    I need your project code , will you please send me the code.It will gonna help me a lot,I will be very grateful if you send your project.