I’m developing an iphone game and I wanted to make users post their scores on facebook. I’ve managed to implement it but every time I want to post the feed there is a facebook window telling me I have loged into my Facebook app, and the user needs to tap accept in order to show the nex window that posts the feed to the profile’s wall.
Do I need to skip the facebook login? I mean facebook authorize method and jump straight into the facebook feed method?
Here’s what I have, however session is always invalid! fbDidLogin never gets called and in debug it gives mes this kind of error:
void SendDelegateMessage(NSInvocation*): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
And if I logout and then try to feed, I have to login 2 times, one for the session and one for the feed.
This is the code:
#import "FacebookConnect.h"
static NSString* kAppId = @"414427041919461"; // Your Facebook app ID here
@implementation FacebookConnect
@synthesize facebook = _facebook;
#pragma mark -
#pragma mark Singleton Variables
static FacebookConnect *singletonDelegate = nil;
#pragma mark -
#pragma mark Singleton stuff
- (id)init {
if (!kAppId) {
NSLog(@"MISSING APP ID!!!");
exit(1);
return nil;
}
if ((self = [super init])) {
_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"]
&& [defaults objectForKey:@"FBExpirationDateKey"]) {
_facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
_facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
}
return self;
}
+(FacebookConnect *) sharedFacebook
{
@synchronized([FacebookConnect class])
{
if(!singletonDelegate) [[self alloc] init];
return singletonDelegate;
}
return nil;
}
+(id)alloc
{
@synchronized ([FacebookConnect class])
{
NSAssert(singletonDelegate == nil, @"Attempted to allocate a second instance of the Game Manager singleton");
singletonDelegate = [super alloc];
return singletonDelegate;
}
return nil;
}
#pragma mark -
#pragma mark Singleton methods
-(void) logout
{
[_facebook logout];
}
-(void) feedWithScore:(int) _s andLevel:(int) _l
{
if (![_facebook isSessionValid]) {
NSLog(@"Session invalid - Authorize");
/*NSArray *permissions = [[NSArray alloc] initWithObjects:@"user_likes", @"read_stream",nil];
[_facebook authorize:permissions];
[permissions release];*/
[_facebook authorize:nil];
}
[_facebook dialog:@"feed" andDelegate:self];
}
#pragma mark -
#pragma mark Facebook implementations
// Pre iOS 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [_facebook handleOpenURL:url];
}
// For iOS 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [_facebook handleOpenURL:url];
}
- (void)fbDidLogin {
NSLog(@"Login OK");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[_facebook accessToken] forKey:@"FBAccessTokenKey"];
[defaults setObject:[_facebook expirationDate] forKey:@"FBExpirationDateKey"];
[defaults synchronize];
}
- (void) fbDidLogout {
NSLog(@"Log out");
// Remove saved authorization information if it exists
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"]) {
[defaults removeObjectForKey:@"FBAccessTokenKey"];
[defaults removeObjectForKey:@"FBExpirationDateKey"];
[defaults synchronize];
}
}
- (void)dialogDidComplete:(FBDialog *)dialog{ NSLog(@"Login OK"); }
- (void)dialogDidNotComplete:(FBDialog *)dialog{}
- (void)dialogCompleteWithUrl:(NSURL *)url{}
- (void)dialog:(FBDialog*)dialog didFailWithError:(NSError *)error{}
- (BOOL)dialog:(FBDialog*)dialog shouldOpenURLInExternalBrowser:(NSURL *)url{return NO;}
- (void)fbDidNotLogin:(BOOL)cancelled{}
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt{}
- (void)fbSessionInvalidated{}
#pragma mark -
#pragma mark Dealloc
-(void) dealloc{
[super dealloc];
[_facebook release];
}
@end
In order to post on a Facebook feed you must have an access token. So you have to authorize to get that token. If you are getting the authorize dialog every time it’s because the access token has expired. You can request offline_access in the old SDK and the new SDK asks that you extend the access_token each time the user uses your app. As an opinion though, you should not “make” a user post to Facebook feed. It should ask them. But that’s just my opinion for a good user experience.
Here is the docs on how to extend the access token.
http://developers.facebook.com/docs/mobile/ios/build/#extend_token
You should also be checking each time your app loads:
And check if it’s already authorized:
See docs here: https://developers.facebook.com/docs/mobile/ios/build/#implementsso