How to retrieve Facebook response using Facebook iOS SDK

I am using the Facebook iOS SDK for iPhone. I initialize the Facebook instance

facebook = [[Facebook alloc] initWithAppId:kAppId];

And then I do login:

[facebook authorize:permissions delegate:self];

After I logged in to Facebook I am doing the following to get the user profile information:

[facebook requestWithGraphPath:@"me" andDelegate:self];
NSMutableData *response = [fbRequest responseText];
unsigned char *firstBuffer = [response mutableBytes];
NSLog(@"Got Facebook Profile: : \"%s\"\n", (char *)firstBuffer);

But I get the following on my console:

Got Facebook Profile: "(null)"

What am I doing wrong, also I believe that Facebook response is a json string and I am looking to get a hold of that json string.


Solution 1:

I thought may be I should make it a wiki and tell the people how I am doing it. because lot of people are facing similar problem.

The first thing that I did was.

In Facebook.m class I added the following statement in the following method

(void)authorizeWithFBAppAuth:(BOOL)tryFBAppAuth
                             safariAuth:(BOOL)trySafariAuth
 trySafariAuth = NO;

This prevents a safari page to get open for the facebook login, but it pops up a screen in app itself. Then i created a helper class for Facebook, the header file code is here.

#import <UIKit/UIKit.h>
#import "FBConnect.h"

@interface FaceBookHelper : UIViewController
<FBRequestDelegate,
FBDialogDelegate,
FBSessionDelegate>{

Facebook    *facebook;
NSArray *permissions;
}


@property(readonly) Facebook *facebook;

- (void)login;

-(void)getUserInfo:(id)sender;

- (void)getUserFriendList:(id)sender;

-(void)postToFriendsWall;

The .m file.

static NSString* kAppId = @"xxx";
#define ACCESS_TOKEN_KEY @"fb_access_token"
    #define EXPIRATION_DATE_KEY @"fb_expiration_date"

@implementation FaceBookHelper

@synthesize facebook;

//////////////////////////////////////////////////////////////////////////////////////////////////
// UIViewController

/**
 * initialization
 */
- (id)init {
    if (self = [super init]) {
        facebook = [[Facebook alloc] initWithAppId:kAppId];
        facebook.sessionDelegate = self;
        permissions =  [[NSArray arrayWithObjects:
                              @"email", @"read_stream", @"user_birthday", 
                              @"user_about_me", @"publish_stream", @"offline_access", nil] retain];
        [self login];
    }
    return self;

}


///////////////////////////////////////////////////////////////////////////////////////////////////
// NSObject

- (void)dealloc {
    [facebook release];
    [permissions release];
    [super dealloc];
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// private

/**
 * Login.
 */
- (void)login {
    // only authorize if the access token isn't valid
    // if it *is* valid, no need to authenticate. just move on
    if (![facebook isSessionValid]) {
           [facebook authorize:permissions delegate:self];
    }
}

/**
 * This is the place only where you will get the hold on the accessToken
 *
 **/
- (void)fbDidLogin {
    NSLog(@"Did Log In");
    NSLog(@"Access Token is %@", facebook.accessToken );
    NSLog(@"Expiration Date is %@", facebook.expirationDate );
    // Store the value in the NSUserDefaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:facebook.accessToken forKey:ACCESS_TOKEN_KEY];
    [defaults setObject:facebook.expirationDate forKey:EXPIRATION_DATE_KEY];
    [defaults synchronize];
    // This is the best place to login because here we know that user has already logged in
    [self getUserInfo:self];
    //[self getUserFriendList:self];
    //[self postToFriendsWall];
}

- (void)fbDidNotLogin:(BOOL)cancelled {
    NSLog(@"Failed to log in");
}

    - (void)getUserInfo:(id)sender {
      [facebook requestWithGraphPath:@"me" andDelegate:self];
    }

    - (void)getUserFriendList:(id)sender {
      [facebook requestWithGraphPath:@"me/friends" andDelegate:self];
    }
////////////////////////////////////////////////////////////////////////////////
// FBRequestDelegate

/**
 * Called when the Facebook API request has returned a response. This callback
 * gives you access to the raw response. It's called before
 * (void)request:(FBRequest *)request didLoad:(id)result,
 * which is passed the parsed response object.
 */
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"Inside didReceiveResponse: received response");
    //NSLog(@"Status Code @", [response statusCode]);
    NSLog(@"URL @", [response URL]);
}

/**
 * Called when a request returns and its response has been parsed into
 * an object. The resulting object may be a dictionary, an array, a string,
 * or a number, depending on the format of the API response. If you need access
 * to the raw response, use:
 *
 * (void)request:(FBRequest *)request
 *      didReceiveResponse:(NSURLResponse *)response
 */
- (void)request:(FBRequest *)request didLoad:(id)result {
    NSLog(@"Inside didLoad");
    if ([result isKindOfClass:[NSArray class]]) {
        result = [result objectAtIndex:0];
    }
    // When we ask for user infor this will happen.
    if ([result isKindOfClass:[NSDictionary class]]){
        //NSDictionary *hash = result;
        NSLog(@"Birthday: %@", [result objectForKey:@"birthday"]);
        NSLog(@"Name: %@", [result objectForKey:@"name"]); 
    }
    if ([result isKindOfClass:[NSData class]])
    {
        NSLog(@"Profile Picture");
        //[profilePicture release];
        //profilePicture = [[UIImage alloc] initWithData: result];
    }
    NSLog(@"request returns %@",result);
    //if ([result objectForKey:@"owner"]) {}

};

/**
 * Called when an error prevents the Facebook API request from completing
 * successfully.
 */
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
  //[self.label setText:[error localizedDescription]];
};


////////////////////////////////////////////////////////////////////////////////
// FBDialogDelegate

/**
 * Called when a UIServer Dialog successfully return.
 */
- (void)dialogDidComplete:(FBDialog *)dialog {
//[self.label setText:@"publish successfully"];
}

@end

Solution 2:

Thanks for this hint Yogesh!

In facebook.m you can also set the safariAuth param in the authorize method.

- (void)authorize:(NSArray *)permissions
     delegate:(id<FBSessionDelegate>)delegate {

  ...

  [self authorizeWithFBAppAuth:YES safariAuth:NO];
}