I have had the Facebook SDK working in the APPDelegate as instructed by the Facebook tutorial, however I am trying to put in into a singleton method. Every tutorial i’ve found seems to be for an older version of the SDK, but I have managed success with this one http://indiedevstories.com/2011/08/30/a-facebook-reusable-class/
I’m having 2 problems, the first is posted here this is the second:
I want a button to post to Facebook, but if the user isn’t logged in then they need to login first then post (without having to press a separate login button first).
I can log in fine, and I can post fine, however I can’t do both together.
If not logged in, the post code shows the login screen, but doesn’t goto the post screen after logging in. you have to press post again.
If you try to login but are already logged in, then nothing happens.
So on the button I use code to login then post, as the login is just skipped if already logged in.
The problem i’m having, is the post code is being run instantly after the login code, so before the user has had a chance to login. This results in 2 popups being opened (1 login and 1 post which displays login as not logged in yet).
How can I get my code to wait for the user to login before moving onto the next line in the code to post?
FacebookHelper.h
@interface FacebookHelper : NSObject <FBSessionDelegate, FBRequestDelegate, FBDialogDelegate, FBLoginDialogDelegate> {
Facebook *_facebook;
NSArray *_permissions;
}
@property (nonatomic,strong) Facebook *facebook;
+(FacebookHelper *) sharedInstance;
+(void)fbDidLogin;
#pragma mark - Public Methods
-(BOOL) isFBSessionValid;
-(void) login;
-(void) logout;
-(void) postToWallWithDialogNewHighscore:(int)highscore;
@end
FacebookHelper.m
@implementation FacebookHelper
@synthesize facebook;
#pragma mark -
#pragma mark Singleton Variables
static FacebookHelper *singletonDelegate = nil;
#pragma mark -
#pragma mark Singleton Methods
+(FacebookHelper *)sharedInstance
{
@synchronized(self) {
if (singletonDelegate == nil) {
singletonDelegate = [[self alloc] init]; // Assignment not done here
}
}
return singletonDelegate;
}
-(id)init
{
self = [super init];
if (self) {
_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
// Restore previous session
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
_facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
_facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
//
}
return self;
}
+(id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (singletonDelegate == nil) {
singletonDelegate = [super allocWithZone:zone];
// assignment and return on first allocation
return singletonDelegate;
}
}
//on subsequent allocation attemps, return nil
return nil;
}
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
#pragma mark - Facebook Delegate Methods
-(void)fbDidLogin
{
NSLog(@"fbDidLogin");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[_facebook accessToken] forKey:@"FBAccessTokenKey"];
[defaults setObject:[_facebook expirationDate] forKey:@"FBExpirationDateKey"];
[defaults synchronize];
}
-(void)fbDidLogout
{
NSLog(@"fbDidLogout");
// Remove saved authorisation information if it exists
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"]) {
[defaults removeObjectForKey:@"FBAccessTokenKey"];
[defaults removeObjectForKey:@"FBExpirationDateKey"];
[defaults synchronize];
}
}
#pragma mark - Public Methods
-(NSMutableDictionary *) buildPostParamsWithHighScore:(int)highscore
{
NSString *customMessage = [NSString stringWithFormat:kCustomMessage, highscore, kAppName];
NSString *postName = kAppName;
NSString *serverLink = [NSString stringWithFormat:kServerLink];
NSString *imageSrc = kImageScr;
//Final params build
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
//@"message", @"message",
imageSrc, @"picture",
serverLink, @"link",
postName, @"name",
@" ", @"caption",
customMessage, @"description",
nil];
return params;
}
-(BOOL) isFBSessionValid
{
// Check if there is a valid session
//_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
_facebook.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"FBAccessTokenKey"];
_facebook.expirationDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"FBExpirationDateKey"];
NSLog(@"accessToken=%@ expirationDaate=%@",_facebook.accessToken,_facebook.expirationDate);
if (![_facebook isSessionValid]) {
NSLog(@"FacebookHelper isFBSessionValid = NO");
return NO;
} else {
NSLog(@"FacebookHelper isFBSessionValid = YES");
return YES;
}
return NO;
}
-(void) login
{
NSLog(@"FacebookHelper login");
_permissions = [NSArray arrayWithObjects:@"publish_stream", nil]; //@"read_stream", @"offline_access"
[_facebook authorize:_permissions];
}
-(void) logout
{
[_facebook logout];
}
-(void) postToWallWithDialogNewHighscore:(int)highscore
{
NSMutableDictionary *params = [self buildPostParamsWithHighScore:highscore];
NSLog(@"Post Feed");
[_facebook dialog:@"feed" andParams:params andDelegate:self];
}
@end
Button Action:
- (IBAction)facebookTest:(id)sender {
[[FacebookHelper sharedInstance] login];
[[FacebookHelper sharedInstance] postToWallWithDialogNewHighscore:123];
}
I have updated the singleton class to post scores to Facebook Wall. Check out the new version: http://indiedevstories.com/2012/04/11/facebookscorer-post-highscores-to-users-facebook-wall/
This new version handles correctly the internal state when authorization and login is required.
HTH