Search code examples
iosfacebookfacebook-ios-sdk

iOS Facebook Publish Feed Dialog doesn't show up after authentication


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?


Solution

  • 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.