views:

1912

answers:

5

This is a repost from the Facebook developer forums, where no-one has responded yet.

This is what I would like to do:

  • user touches Connect button
  • code retrieves session and attempts to resume
  • if session does not resume, pop up login dialog
  • pop up feed dialog (after user has successfully logged in)

What actually happens in the case where a login is needed:

  • user touches Connect button
  • login dialog comes up (but user never sees it)
  • feed dialog immediately comes up on top of it
  • feed dialog spins forever because it is unable to connect

There doesn't seem to be a way to use the delegate methods to tell if the user has finished logging in; dialogDidSucceed never seems to be called for the login dialog. For that matter, there doesn't seem to be a way to tell if they cancelled out either (in which case going on to the feed dialog would be pointless).

Am I attempting the impossible?

+1  A: 
- (void) login {
  session = [FBSession sessionForApplication:... secret:... delegate:self];
  FBLoginDialog *dialog = [[[FBLoginDialog alloc] initWithSession:session] autorelease];
  dialog.delegate = self;
  [dialog show];
}

- (void) session:(FBSession *)newSession didLogin:(FBUID)newUid {
  session = newSession;
  uid = newUid;

  FBFeedDialog* dialog = [[[FBFeedDialog alloc] init] autorelease];
  dialog.delegate = self;
  dialog.templateBundleId = ...
  dialog.templateData = ...
  [dialog show];
}
Ed Marty
A: 

(I'm "answering my own question" because this was too long to leave as a comment on the previous entry)

I don't think I explained the problem clearly enough... let me try again. The code below is executed when the user touches the "share on facebook" button:

// get session
if (session == nil) {
    session = [FBSession sessionForApplication.....];
}
// log in if necessary
if (![session resume]) {
    FBLoginDialog* dialog = [FBLoginDialog alloc...];
    [dialog show];
}
// post feed story
FBFeedDialog* dialog = [FBFeedDialog alloc...];
dialog.delegate = self;
dialog.templateBundleID = ...;
[dialog show];

This does not work, for obvious reasons - both dialogs come up right away. While I see that splitting it into two methods would help, the main problem is that I have nothing on which to trigger bringing up the feed dialog. dialogDidSucceed doesn't seem to get called for the login dialog, and there doesn't seem to be anything else I can look for. Most apps split this into two buttons, meaning the user has to touch a second button in order to initiate posting a feed story. I was hoping to avoid that, but I can't find a way to do it.

Janine
A: 

While Ed's answer is correct, he's not explaining why.

When you send the show message the first dialog, it shows, but doesn't wait for it to close.. the program execution moves along to the next line. Therefore you are asking the next dialog to show, which it does – right on top of the previous one. This is true for dialogs or alert views on the iPhone platform.

Ed's answer is showing the first dialog but not continuing. What is not obvious, is that when the user successfully logs in, the session delegate is sent the -didLogin: message. You may have expected a dialog delegate message?

Be careful though, as other situations that you code may result in the session login, and it will run the code in the delegate method.. and you may not want that!

An example of this is when the session resumes. To keep it straight-forward, assume you have two actions in your app, and both publish a short story to the user feed. When you ask the user to login – or resume – their existing session, the session delegate message -didLogin: will be sent. You need to make sure your implementation of -didLogin: handles both situations, and both actions.

As an aside, consider using the latest SDK and the stream.publish request, or the FBStreamDialog class (instead of FBFeedDialog)for pushing the story to facebook.

ohhorob
Thank you! Yes, I understood what was wrong with my code but not how to fix it, and the pointer to the session delegate is what I needed. I had thought that both the login and feed dialogs would implement the dialog delegate but the login one doesn't.I'm not sure I understand your last sentence, though. What sort of situation would trigger the session login without them actually having logged in?Thanks again!
Janine
Hi Janine, I've updated my answer to be more specific.
ohhorob
Thanks, I get it now. I was just looking at FBStreamDialog... wish they had provided a bit more detail, but I'll figure it out.
Janine
A: 

Can I ask a follow-up on this, as I'm also experiencing the same problem and don't clearly understand how to resolve this (noob developer so apologize in advance)? What specifically is the solution? I have several places in my app where I want to allow the user to publish to their wall (via the FBFeedDialog). I have a place in a Settings window where the user can login via FBConnect login, and when they're logged-in successfully, the FBFeedDialog works great. However if they've logged-out (from the Settings window), and they try to publish from other areas in my app, I'd like to be able to A) query if they're logged-on, and if not B) produce the login prompt/dialog box, and after successfully logging-in, C) publish the feed. Right now it's working the same as originally described, where the FBFeedDialog appears on top of the FBLoginDialog with the wheel spinning. When I close that dialog, the login dialog is visible.

Many thanks in advance!

A: 

So I've been messing with facebook connect for about 10 hours now, and I still am not able to send a query using fql to Facebook and get back anything let alone keep my app from crashing. Basically, when I try to log in, it never calls the session:didLogin: function, where I'm trying to send my query from. And when I try to send it manually, the console says:

2010-01-19 22:44:49.821 Facebook[3396:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: session_key)' 2010-01-19 22:44:49.823 Facebook[3396:207] Stack ( 29373531, 2446402825, 29457467, 29457306, 162565, 23131, 9411, 2802777, 3210146, 3218883, 3214095, 2907699, 2816028, 2842805, 37469905, 29158272, 29154376, 37463949, 37464146, 2846723, 8516, 8370 )

PLEASE HELP ME!!!!!!!! I've provided my source files below.

Here's my header:

// // FacebookViewController.h // Facebook // // Created by Austin on 1/19/10. // Copyright Dunham Academy 2010. All rights reserved. //

import

import "FBConnect/FBConnect.h"

@interface FacebookViewController : UIViewController { FBSession *session; } //method called when I press button on screen -(IBAction)Query;

@end

Here's my implementation:

// // FacebookViewController.m // Facebook // // Created by Austin on 1/19/10. // Copyright Dunham Academy 2010. All rights reserved. //

import "FacebookViewController.h"

import "FBConnect/FBSession.h"

@implementation FacebookViewController

/* // The designated initializer. Override to perform setup that is required before the view is loaded. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { // Custom initialization } return self; } */

/* // Implement loadView to create a view hierarchy programmatically, without using a nib. - (void)loadView { } */

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; session = [[FBSession sessionForApplication:@"Actual API KEY" secret:@"Actual Secret Key" delegate:self] retain]; FBLoginButton* button = [[[FBLoginButton alloc] init] autorelease]; [self.view addSubview:button]; }

-(IBAction)Query { NSString* fql = [NSString stringWithFormat:@"select uid,name from user where uid == %lld", aVariableForMyUserIDWhichIKnow]; NSDictionary* params = [NSDictionary dictionaryWithObject:fql forKey:@"query"]; [[FBRequest requestWithDelegate:self] call:@"facebook.fql.query" params:params];

}

  • (void)request:(FBRequest*)request didLoad:(id)result {

NSLog(@"awesome"); }

  • (void)request:(FBRequest*)request didFailWithError:(NSError*)error {

}

  • (void)session:(FBSession*)session didLogin:(FBUID)uid { //This NSLog has never gotten displayed, which means this function has never been called... weird NSLog(@"hi"); NSString* fql = [NSString stringWithFormat:@"select uid,name from user where uid == %lld", uid]; NSDictionary* params = [NSDictionary dictionaryWithObject:fql forKey:@"query"]; [[FBRequest requestWithDelegate:self] call:@"facebook.fql.query" params:params]; }

  • (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use. }

  • (void)viewDidUnload { [session logout]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; }

  • (void)dealloc { [super dealloc]; [session.delegates removeObject: self]; [session release], session = nil; }

@end