9

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.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Yogesh
  • 1,333
  • 3
  • 16
  • 35

2 Answers2

25

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
YogiAR
  • 2,207
  • 23
  • 44
Yogesh
  • 1,333
  • 3
  • 16
  • 35
  • NB: The Facebook iOS SDK opens up an authentication page in Safari so users don't need to login if they are already logged in via Safari. Browser cookies on iOS are separate for each UIWebView. So while the in-app approach above is neater, it requires more work from the user! iOS5 might make this easier, but it only supports Twitter right now (this much is public knowledge and not under NDA). – pchap10k Jun 09 '11 at 11:54
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];
}
Martin
  • 326
  • 4
  • 9