Thanks for reading.
I went through Facebook iOS SDK Feed Dialog issue after authentication but in vain.
What works: I created a sample "Hello, World" app using the Facebook iOS Tutorial with the Feed Dialog. This tutorial works fine and I am able to see the post in my feed.
Problem: When I integrated this code in my app, I don't get to see the Feed Dialog after the authentication when the control reaches back to my app.
Flow of control:
I have a UIImagePickerController
showing a camera that takes a picture, then shows UIAlertView
to indicate that the image is being uploaded, shows a UIAlertView
to display the result returned from server, and then finally shows a UIActionSheet
to display the different sharing options (share to Facebook, Twitter, etc.).
When the user hits "Share to Facebook", the following selector
gets invoked:
- (void) initFacebook
{
//Init Facebook
facebook = [[Facebook alloc] initWithAppId:@"308136969223987" andDelegate:self];
//Check for access_token
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:@"FBAccessTokenKey"]
&& [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
if(![facebook isSessionValid]) {
[facebook authorize:nil];
}
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
kAppId, @"app_id",
@"https://developers.facebook.com/docs/reference/dialogs/", @"link",
@"http://fbrell.com/f8.jpg", @"picture",
@"Facebook Dialogs", @"name",
@"Reference Documentation", @"caption",
@"Using Dialogs to interact with users.", @"description",
@"Facebook Dialogs are so easy!", @"message",
nil];
[_facebook dialog:@"feed" andParams:params andDelegate:self];
}
This launches the Facebook app to authenticate, and then opens my app again with the UIImagePickerController
but doesn't show the Feed Dialog
.
Can someone please help me out?
You have to manually call the method you want again, in your case -(void)initFacebook, in the -(void)fbDidLogin of the FBSessionDelegate.
In addition, to make this more generic, a little trick I did after [facebook authorize:nil]; I set a pending target and selector to store the pending command that needs to be executed after login. Something like this...
id fbPendingTarget;
SEL fbPendingAction;
if (![delegate.facebook isSessionValid]) {
[delegate.facebook authorize:nil]; // Facebook app or Safari login, mustitask
// Save pending actions
delegate.fbPendingTarget = self;
delegate.fbPendingAction = @selector(facebookButtonPressed);
[self retain]; // *** hold on to self if you will release self and is using fbPendingTarget as self
}
and when the delegate fires, it runs your pending action ...
- (void)fbDidLogin {
[self storeAuthData:[facebook accessToken] expiresAt:[facebook expirationDate]];
[self apiFQLIMe]; // request user info
// perform any pending actions after login
if ([fbPendingTarget respondsToSelector:fbPendingAction]) {
[fbPendingTarget performSelector:fbPendingAction];
}
self.fbPendingTarget = nil;
self.fbPendingAction = nil;
[self release]; // *** let go of self after we finished everything
}
This help executing any pending actions you need after login. And don't forget to clear them after executing or login failed.
-(void)fbDidNotLogin:(BOOL)cancelled {
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:@"Cannot Connect"
message:@"There was an error while connecting to Facebook. Please try Again."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil] autorelease];
[alertView show];
self.fbPendingTarget = nil;
self.fbPendingAction = nil;
[self release]; // *** let go of self after we finished everything
}
Hope this helps :)
Edit: I find it better to set fbPendingTarget
to some object that exists throughout the app lifetime (like appDelegate
) rather than setting to self
. This is because in many cases your self
is a view that will be released right after the user sends a post to Facebook. Sending a message to a released object will crash your app.
A dirty way to get around this is to explicitly use [self retain]
before sending and then [self release]
in your fbPendingAction
. But that would retain everything else that should be released in self by that time. I just find it easier to set to appDelegate
since most action you will do is just displaying an alert anyway. I'll edit the code just for safety sake.