facebook isSessionValid is always NO - iphone

hi i use the newest facebook api with SSO and do implement like following in my viewController (not in the appDelegate like in the example if that makes any difference):
in my .h file
Facebook *facebook;
#property (nonatomic,retain) Facebook *facebook;
in my .m file i do the following in my viewDidLoad
self.facebook = [[Facebook alloc] initWithAppId:#"myappID"];
in another method I do
if (![facebook isSessionValid]) {
NSArray *permissions = [[NSArray arrayWithObjects:#"publish_stream",nil] retain];
[facebook authorize:permissions delegate:self];
}
but it seems that isSessionValid is alway NO
and I don't know why!
does anybody have any idea why ?
oh and also expirationDate and accessTokken are nil

I had this exact same problem yesterday, it seems you must persist and restore the access token/expiration date yourself.
In your viewDidLoad:
// Restore previously saved Facebook credentials (If any)
facebook.accessToken = [[NSUserDefaults standardUserDefaults] stringForKey:#"FBAccessToken"];
facebook.expirationDate = (NSDate *) [[NSUserDefaults standardUserDefaults] objectForKey:#"FBExpirationDate"];
// Trigger SSO Facebook authentication if required
if ([facebook isSessionValid] == NO) {
[facebook authorize:nil delegate:self];
} else {
[self fbDidLogin];
}
Then in the fbDidLogin delegate:
- (void)fbDidLogin
{
// Save the users access token and expiration date so we can restore it later
// This way we can avoid needlessly authenticating to Facebook.
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.accessToken forKey:#"FBAccessToken"];
[[NSUserDefaults standardUserDefaults] setObject:self.facebook.expirationDate forKey:#"FBExpirationDate"];
// User has logged in to Facebook, now get their userId from Facebook
[facebook requestWithGraphPath:#"me" andDelegate:self];
}
So now users will have to login/authorize your application once and from then on their session will remain valid until they logout of Facebook.

alright here is the answer to my problem.
as I said in the comment also the application:handleOpenURL: never got called!
cause I had this method in my ViewController and apparently it has to be in the appDelegate!
so in my Navigationbar based application I did the following in my appDelegate:
in the .h file:
ViewController *viewController;
#property (nonatomic, retain) IBOutlet ViewController *viewController;
in the .m file:
#synthesize viewController;
viewController = [[ViewController alloc]init];
[self.navigationController pushViewController:viewController animated:NO];
and then implemented the method like that:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [viewController.facebook handleOpenURL:url];
}
and of course in my ViewController I did everything #Tyler mentioned (thank you for that)
and everything works like a charm.
hope this helps everyone with the same problem.

Related

Setting up connection to Facebook not working as expected (iPhone)

I'm trying to create a connection to Facebook however I'm having an issue with the handling of the openUrl.
In the past I've been able to add the following in my app delegate class:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [[viewController facebook] handleOpenURL:url];
}
Which has worked as I would expect. However, this time I have a slightly different situation in the sense that the viewController is loaded elsewhere in the app. To get around this problem I came up with an idea of creating a new class that is responsible for handling the connection, but can also be accessed from the class where I create the Facebook post.
To explain further here is the relevant code in my app delegate class
.m
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
FacebookConnectionHandler *fbConnHandler = [[FacebookConnectionHandler alloc] init];
return [[fbConnHandler facebook] handleOpenURL:url];
}
Then here is the code in the FacebookConnectionHandler class:
.h
#import <Foundation/Foundation.h>
#import "Other_ViewController.h"
#import "Facebook.h"
#interface FacebookConnectionHandler : NSObject <FBSessionDelegate>
{
Other_ViewController *otherView;
Facebook *facebook;
}
#property(nonatomic, strong)Other_ViewController *otherView;
#property(nonatomic, strong)Facebook *facebook;
+ (id)sharedManager;
#end
.m
#import "FacebookConnectionHandler.h"
#implementation FacebookConnectionHandler
#synthesize otherView;
#synthesize facebook;
static FacebookConnectionHandler *mySingleton = nil;
+ (id)sharedManager
{
#synchronized(self)
{
if (mySingleton == nil) mySingleton = [[self alloc] init];
}
return mySingleton;
}
- (void)fbDidLogin
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
// Allow the user to create a post
[self.otherView createFacebookPost];
}
#end
Finally... here is the relevant code in the Other_ViewController class (where the post is being created):
.h
#import "FBConnect.h"
#interface Other_ViewController : UIViewController <FBSessionDelegate>
{
Facebook *facebook;
}
#property(nonatomic, retain)Facebook *facebook;
- (void)createFacebookPost;
#end
.m
- (void)createFacebookPost
{
// Create the post
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"Blah", #"name",
#"", #"caption",
#"", #"description",
#"http://www.xyz.com", #"link",
#"", #"picture",
nil];
// Post it to the users feed
[facebook dialog:#"feed" andParams:params andDelegate:nil];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex)
{
case kFacebookButton:
{
if (facebook == nil || ![facebook isSessionValid])
{
// Setup Facebook connection
facebook = [[Facebook alloc] initWithAppId:#"1111111111" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"])
{
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
// Set the connection handler
FacebookConnectionHandler *fbConnectionHandler = [[FacebookConnectionHandler alloc] init];
fbConnectionHandler.mapView = self;
fbConnectionHandler.facebook = self.facebook;
if (![facebook isSessionValid])
{
NSArray *permissions = [[NSArray alloc] initWithObjects:#"publish_actions", nil];
[facebook authorize:permissions];
}
}
else
{
// Create the post
[self createFacebookPost];
}
break;
}
default:
break;
}
}
I may be going about this in completely the wrong way and have completely overcomplicated the problem, however I'm new to the whole facebook SDK and at this point I'm really stumped. Please can someone offer a solution?
Note: To be clear, the issue is that the method fbDidLogin is not being called, thus the rest of the code doesn't get a chance to run.
You're not using your singleton in the app delegate, you're creating a new instance of your connect handler class :
Instead of
FacebookConnectionHandler *fbConnHandler = [[FacebookConnectionHandler alloc] init];
return [[fbConnHandler facebook] handleOpenURL:url];
try
return [[[FacebookConnectionHandler sharedManager] facebook] handleOpenURL:url];
You're also not using the singleton in your Other_ViewController class.
If you are going to have the singleton architecture pattern you have to remember to always use the sharedManager and never alloc/init a new one :)
I sometimes make init throw an exception to remind me that there is a singleton method.
static FacebookConnectionHandler *mySingleton = nil;
- (id)init {
#throw [NSException exceptionWithName:self.class.description reason:#"Please use the sharedManager, don't make a new one of these!" userInfo:nil];
}
- (id)initInternal {
// Put your real init stuff in here
}
+ (id)sharedManager
{
#synchronized(self)
{
if (mySingleton == nil) mySingleton = [[self alloc] initInternal];
}
return mySingleton;
}
PS Using a separate Facebook class is exactly the way I've done it in apps I've written before - your architecture is fine :) I would also consider making the Facebook connection hander class responsible for making it's own Facebook instance instead of the view controller having to do it :)

Facebook's FBConnect SDK issues on iOS

I'm using FBConnect sdk in order to publish posts to a user's profile via my application. I'm having a number of problems with this:
When the relevant code runs for the first time on the device, the user is re-directed, as wanted, to the facebook app/website, which asks him to authorize it. if the user authorizes it, it returns back to the application, which pops a "Connect to facebook" view controller which asks the user to log in. this is weird, as the user is already logged in, otherwise how could he authorize the app? but I guess this may be ok, as he hadn't logged in through the app yet. after he logs in, it does nothing. only the second time the code gets run, after he authorized the app, the user gets the posting dialog.
If the user hadn't authorized the app, when it comes back to my app after the authorization dialog, it asks the user to login ( just as if he authorized ), and does nothing after he had logged in. only the second time the code gets ran, the authorization dialog opens, with the optinos "Authorize" & "Leave App", instead of "Authorize" & "Don't authorize" / "Allow" & "Don't Allow".
In addition, if the user has deleted his authorization via his account's settings on facebook, instead of just asking him to re-authorize it, a facebook dialog pops ( instead of the post/authorization dialog ), saying: "An error occurred. Please try again later." Trying later doesn't help. it will pop always, even if u restart the app. the only way to make it go away is to re-install the app, which will cause it to re-pop the authoriziation dialog.
So here's what I want to achieve:
After the user authorizes the app, he wouldn't have to log in again.
After the user authorizes the app, the posting dialog will pop immedietly, without him having to re-run the code ( which is triggered, btw, with a button ).
If the user un-authorizes the app, he will be prompted again with the authorization dialog, instead of the error dialog
If he refused the authorization, I will call a function that displays an error/etc.
Here's the relevant code:
MyViewController.m
- (void)shareOnFacebook
{
Facebook *facebook = [[Facebook alloc] initWithAppId:myAppID];
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] setFacebook:facebook];
[facebook release];
facebook = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] facebook];
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:[NSArray arrayWithObjects:#"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
}
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
//Giving the dictionary some parameters for posting defaults
[facebook dialog:#"feed" andParams:dictionary andDelegate:self]; //Note: we have 2 different delegates! appDelegate for connections & url switching, and self for dialogs
}
MyAppDelegate.h
#interface MyAppDelegate : NSObject <UIApplicationDelegate, FBSessionDelegate, FBDialogDelegate>
{
Facebook *facebook; // kept for facebook sharing, accessed only from MyViewController although delegate methods are handeled in here
}
#property (nonatomic, retain) Facebook *facebook;
#end
MyAppDelegate.m
- (void)fbDidLogin
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [self.facebook handleOpenURL:url];
}
Is it possible that I'm missing a couple of delegate functions on MyViewController? Because I see for some reason I've marked it as implementing the FBDialogDelegate protocol, although he doesn't implement any function from there.
I'd be really glad if you guys would help me, as this is extremely frustrating for me. I couldn't find nothing about this on the internet, and I feel like im drowning in here.Tnx in advance!
First:
[facebook authorize:[NSArray arrayWithObjects:#"publish_stream",#"offline_access",nil] delegate:self];
The offline_access key here will keep your auth token alive forever (or, more specifically, until the user manually de-authorizes your application in their application settings in their Facebook account settings). Also, set your active VC as the delegate (more on that later).
Secondly:
-(void)popUserShareFeed {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
//Giving the dictionary some parameters for posting defaults
[facebook dialog:#"feed" andParams:dictionary andDelegate:self];
}
Call this method (or one like it) in your -fbDidLogin delegate method. Also call it in your original method if the session was still valid, i.e.:
if (![facebook isSessionValid]) {
[facebook authorize:[NSArray arrayWithObjects:#"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
} else {
[self popUserShareFeed];
}
...and your new fbDidLogin:
- (void)fbDidLogin
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[self popUserShareFeed];
}
(Note: you'll have to define this in MyViewController.m and use it as your FBSessionDelegate. It will be functionally equivalent. Your AppDelegate does not need to also be your FBSessionDelegate.
Third:
Implement the -fbDidNotLogin:(BOOL)cancelled FBSessionDelegate method, like so:
-(void)fbDidNotLogin:(BOOL)cancelled {
if (cancelled) {
... some alert about the user cancelling...
} else {
... some alert about how it failed for some reason...
}
}
Fourth, as far as your bizarro errors go: A) the Facebook SDKs in general are not great, and B) I'd only set the auth token and the expiration date on your facebook object if
A) you don't already have one instantiated (i.e., it's nil)
and
B) the expirationDate you're setting is in the future (i.e. timeIntervalSinceNow [the NSDate instance method] called on it returns > 0).
Sounds like you're experiencing the same issue described in this Facebook Platform Developer forum post. I'm encountering the same problem, but on the web. Only one response was given from Facebook in that thread, and it's wrong information.
Facebook has the worst developer docs and developer support ever, I wouldn't hold my breath waiting on a solution.
I had similar but not the same problem: message "An error occurred. Please try again later." was shown always.
The problem was with not properly configured App ID - it was provided by customer (so I'm not sure what exactly was wrong); everything works properly since I replaced it with my own test App ID (from previous app).
I have integrated FBConnect in so many applications , but never face such kind of critical issue. So, there would be something missing in your code:
Insted of checking FBAccessTokenKey & FBExpirationDateKey, simply try with session object of FBSession class of FBConnect.
Just try using mine code with few conidtions:
session = [[FBSession sessionForApplication:#"key" secret:#"AppSecretKey" delegate:self] retain];
[session resume];
_posting = YES;
// If we're not logged in, log in first...
if (![session isConnected]) {
loginDialog = nil;
loginDialog = [[FBLoginDialog alloc] init];
[loginDialog show];
}
// If we have a session and a name, post to the wall!
else if (_facebookName != nil) {
[self postToWall]; // Over here posting dialog will appear , if user has already logged in or session is running.
}
}
else {
[FBBtn setTitle:#"Login" forState:UIControlStateNormal]; // if you want to change the title of button
[session logout];
}
Additionally take care of releasing the session object in dealloc method only , rather than releasing it in any other method.
- (void)dealloc {
[super dealloc];
[session release];
session = nil;
}
Hope that would solve your problem.
Not a direct solution for your code problems, but...
Have you consider using an open-source library for this? ShareKit is a great example: http://getsharekit.com . The integration is dead simple and it does everything you need.
I was having the exact same issue, and used Ben Mosher's response above, but I also decided to create a simple singleton class for the Facebook object, so that in my AppDelegate I can handle the following function properly:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[[FBManager defaultManager] facebook] handleOpenURL:url];
//return [facebook handleOpenURL:url];
}
My singleton class is both FBSessionDelegate and FBDialogDelegate, so it handles the corresponding methods.
This allows me to only prompt the user to login when they are actually trying to post something, instead of when the app launches.

iphone app delegate with logic + facebook connect?

i'm really stuck on this one so please help!
I'm writing an app that implements facebook connect so when the app starts, I need it to check to see if it has a valid facebook access token, AND also check if their appKey that i provide is still valid (i don't want more than 1 account logged in at a time). so what needs to happen is..
App starts -> get facebook/my access key/token from NSUserDefaults -> send my appkey to a server to make sure it's still valid -> if valid then show my tableviewcontroller.
if it fails anywhere else(facebook access token isn't valid, or their appkey for my app isn't valid), then they will be taken to a View with the facebook connect button. after they login from there, they will be shown the tableviewcontroller
I don't know how to structure my app delegate and view controllers for this to work. From what I know about the facebook connect, most of the stuff has to happen in the delegate because facebook's application:handleOpenUrl: and fbDidLogin methods have to be called in the app delegate but if i do a
self.window.rootViewController = self.tableController
or
self.window.rootViewController = self.loginButtonViewController
before that, then i won't have access to these methods
Do i need to put in a delegate or something from the view controller back to the app delegate? i have no clue..
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
facebook = [[Facebook alloc] initWithAppId:#"MY_APP_ID"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
NSString *myKey;
if ([defaults stringForKey:#"myKey"]) {
myKey= [[NSString alloc] initWithString:[defaults stringForKey:#"myKey"]];
}
else{
myKey = [[NSString alloc] initWithString:#""];
}
//SEND THE KEY + FBID TO SERVER
if ([facebook isSessionValid] /*&& [response==OK]*/) {
self.window.rootViewController = self.navController;
//delegate data to EventsTableController
}
else{
self.window.rootViewController = self.loginController;
}
[self.window makeKeyAndVisible];
return YES;
}
- (void)fbDidLogin {
NSLog(#"did login");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
NSString *myKey;
[facebook requestWithGraphPath:#"me" andDelegate:self];
if ([defaults stringForKey:#"myKey"]) {
myKey= [[NSString alloc] initWithString:[defaults stringForKey:#"myKey"]];;
}
else{
myKey= [[NSString alloc] initWithString:#""];
}
//NSString *validKey = [[NSString alloc] initWithString:#"OK"];
//Send myKey and validKey to server
//server will do its thang and send data
[self.window addSubview:self.navController.view];
[self.window makeKeyAndVisible];
}
thanks in advance
What means myKey?
In facebook.h, the method isSessionValid uses only two variables. (accessToken, expirationDate)
- (BOOL)isSessionValid {
return (self.accessToken != nil && self.expirationDate != nil
&& NSOrderedDescending == [self.expirationDate compare:[NSDate date]]);
}
You should have moved above code to RootViewController.m not AppDelegate.m
Because MainWindow.xib can recognize only one RootView.
(In your case, you wanted to have more RootView, navController, loginController)
See this Page
So, I suggest that you move your authorization code to RootViewController.m
(etc. viewDidLoad or viewWillAppear methods)
Next, in RootViewController, try to change your view according to whether session is valid or not.
And try Again! It will work!

iPhone Facebook app: Where does the "permissions array" code go?

I just went through the "Getting Started > Mobile Apps" documentation on Facebook developers. They provided the code to ask permission for accessing information but they don't specify where that code is suppose to go.
Could you tell me where to put the code? Because I don't want to put it in the wrong space.
The code I want to add:
NSArray* permissions = [[NSArray arrayWithObjects:
#"publish_stream", #"offline_access", nil] retain];
[facebook authorize:permissions delegate:self];
My appDelegate code:
#import "iOSTestAppDelegate.h"
#implementation iOSTestAppDelegate
#synthesize facebook;
#synthesize viewController=_ViewController;
#synthesize window=_window;
#synthesize managedObjectContext=__managedObjectContext;
#synthesize managedObjectModel=__managedObjectModel;
#synthesize persistentStoreCoordinator=__persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
/* Step 2. Within the body of the application:didFinishLaunchingWithOptions: method create instance of the Facebook class using your app id */
facebook = [[Facebook alloc] initWithAppId:#"********"];
/* Step 3. Once the instance is created, check for previously saved access token information. */
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
/* Step 4. Check for a valid session and if it is not valid call the authorize method which will both signin the user and prompt the user to authorize the app: */
if (![facebook isSessionValid]) {
[facebook authorize:nil delegate:self];
}
return YES;
}
/* Step 5. Add the application:handleOpenURL: method to the AppDelegate with a call to the facebook instance: */
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
/* Step 6. Implement the fbDidLogin method from the FBSessionDelegate implementation. In this method you will save the user's credentials specifically the access token and corresponding expiration date. */
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
...
#end
After allocate your facebook instance, you have to provide these permission for authorizing the facebook from the user_credentials. it means were getting these permission from the user who are login.
facebook=[[Facebook alloc]initWithAppId:kAppId];
_permissions = [[NSArray arrayWithObjects:#"publish_stream",#"offline_access",nil]retain];
[facebook authorize:_permissions delegate:self];
Publish stream provides : Enables your app to post content, comments, and likes to a user's stream and to the streams of the user's friends. With this permission, you can publish content to a user's feed at any time, without requiring offline_access. However, please note that Facebook recommends a user-initiated sharing model.
Offline Access:
Enables your app to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived.
Refer more details about permission here

Saving Facebook access_token in NSUserDefaults on iOS

iOS beginner here. I'm using the following code to save my facebook accessToken and expirationDate in NSUserDefaults:
facebook = [[Facebook alloc] initWithAppId:#"225083222506272"];
[facebook authorize:nil delegate:self];
NSString *access=[facebook accessToken];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:access, #"accessToken",[facebook expirationDate], #"expirationDate",nil];
[defaults registerDefaults:appDefaults];
And I'm trying to retrieve accessToken and expirationDate in a later call with:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *access=[defaults valueForKey:#"accessToken"];
NSDate *date=[defaults objectForKey:#"expirationDate"];
[facebook fbDialogLogin:access expirationDate:date];
but access and date are null. What am I doing wrong?
The code here is not synchronous. It means it does not block after the call to [facebook authorize:nil delegate:self];. You should instead implement the fbDidLogin delegate method to be notified of when the user has actually logged in successfully. At that point, retrieve the access tokens and save them to user defaults.
Here's a partial sample:
- (void)userClickedFacebookLogin {
[facebook authorize:nil delegate:self]; // delegate is self
}
// Delegate method that you should implement to get notified
// when user actualy logs in.
- (void)fbDidLogin {
// now get the access token and save to user defaults
NSString *access = [facebook accessToken];
// ..
}
Also make sure that the class which has the above code implements the FBSessionDelegate protocol at minimum.
#interface MyClass <FBSessionDelegate> {
}
#end
Look at the DemoApp sample and specifically the DemoAppViewController class from Facebook to get a better idea.