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 :)
Related
Hi I am using AFNetworking in my IOS app and I am unable to maintain session. I am using an AFNetworking client and using it in all requests to the server.
I have gone through the following questions: How to manage sessions with AFNetworking , but I don't plan to manipulate the cookies or the session. I intend to implement a session throughout the life cycle of the app.
My AFNetworking client's .m is as follows
#implementation MyApiClient
+(MyApiClient *)sharedClient {
static MyApiClient *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[MyApiClient alloc] initWithBaseURL:[GlobalParams sharedInstance].baseUrl];
});
return _sharedClient;
}
-(id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]];
self.parameterEncoding = AFFormURLParameterEncoding;
return self;
}
#end
and I make the following requests to the server on the call of "- (void)searchBarSearchButtonClicked:(UISearchBar *)search" -->>
NSString *path = [NSString stringWithFormat:#"mobile"];
NSURLRequest *request = [[MyApiClient sharedClient] requestWithMethod:#"GET" path:path parameters:#{#"q":search.text}];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request,
NSHTTPURLResponse *response, id json) {
// code for successful return goes here
NSLog(#"search feed %#", json);
search_feed_json = [json objectForKey:#"searchFeed"];
if (search_feed_json.count > 0) {
//<#statements-if-true#>
show_feed_json = search_feed_json;
//reload table view to load the current non-empty activity feed into the table
[self.tableView reloadData];
} else {
//<#statements-if-false#>
NSLog(#"Response: %#", #"no feed");
}
} failure :^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// code for failed request goes here
NSLog(#"nops : %#", error);
}];
[operation start];
Can anyone please guide me or point out where I am wrong ?
Any help would be appreciated.
Thanks in advance.
Edit ::
I found my answer in the following post : https://stackoverflow.com/a/14405805/1935921
I initialised the methods listed in the answer in my GlobalParams class, which contains all the Global parameters and methods.
I call the "saveCookies" method when the app does the login and the server sends the Cookies.
Then these cookies are loaded every time I make any subsequent request by using the method "loadCookies". The Code looks as follows :
GlobalParams.h
#import <Foundation/Foundation.h>
#interface GlobalParams : NSObject
// Your property settings for your variables go here
// here's one example:
#property (nonatomic, assign) NSURL *baseUrl;
// This is the method to access this Singleton class
+ (GlobalParams *)sharedInstance;
- (void)saveCookies;
- (void)loadCookies;
#end
GlobalParams.m
#import "GlobalParams.h"
#implementation GlobalParams
#synthesize myUserData,baseUrl;
+ (GlobalParams *)sharedInstance
{
// the instance of this class is stored here
static GlobalParams *myInstance = nil;
// check to see if an instance already exists
if (nil == dronnaInstance) {
myInstance = [[[self class] alloc] init];
myInstance.baseUrl = [NSURL URLWithString:#"http://www.test.dronna.com/"];
}
// return the instance of this class
return myInstance;
}
- (void)saveCookies{
NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject: cookiesData forKey: #"sessionCookies"];
[defaults synchronize];
}
- (void)loadCookies{
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: #"sessionCookies"]];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookies){
[cookieStorage setCookie: cookie];
}
}
#end
then I call " [[GlobalParams sharedInstance] saveCookies]; " or " [[GlobalParams sharedInstance] loadCookies]; "(depending on read/write required in cookies) in all my server calls after defining the NSMutableRequest.
I hope this helps somebody.
I found my answer in the following post : https://stackoverflow.com/a/14405805/1935921
I initialised the methods listed in the answer in my GlobalParams class, which contains all the Global parameters and methods. I call the "saveCookies" method when the app does the login and the server sends the Cookies. Then these cookies are loaded every time I make any subsequent request by using the method "loadCookies". The Code looks as follows :
GlobalParams.h
#import <Foundation/Foundation.h>
#interface GlobalParams : NSObject
// Your property settings for your variables go here
// here's one example:
#property (nonatomic, assign) NSURL *baseUrl;
// This is the method to access this Singleton class
+ (GlobalParams *)sharedInstance;
//saving cookies
- (void)saveCookies;
//loading cookies
- (void)loadCookies;
#end
GlobalParams.m
#import "GlobalParams.h"
#implementation GlobalParams
#synthesize myUserData,baseUrl;
+ (GlobalParams *)sharedInstance
{
// the instance of this class is stored here
static GlobalParams *myInstance = nil;
// check to see if an instance already exists
if (nil == dronnaInstance) {
myInstance = [[[self class] alloc] init];
myInstance.baseUrl = [NSURL URLWithString:#"http://www.test.dronna.com/"];
}
// return the instance of this class
return myInstance;
}
- (void)saveCookies{
NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject: cookiesData forKey: #"sessionCookies"];
[defaults synchronize];
}
- (void)loadCookies{
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: #"sessionCookies"]];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookies){
[cookieStorage setCookie: cookie];
}
}
I'm having a lot of trouble posting comments to Facebook. Here is how I have got the code setup; in my viewController class I have set up a button that when pressed checks if the user is connected to Facebook. If they're not connected I attempts to make a connection. Here is the code the .h and .m files:
.h file
#import <UIKit/UIKit.h>
#import "FBConnect.h"
#interface Info_Main_ViewController : UIViewController <FBSessionDelegate>
{
Facebook *facebook;
}
#property(nonatomic, retain)Facebook *facebook;
- (IBAction)shareButtonPressed:(id)sender;
- (void)setUpFacebookConnection;
.m file
- (IBAction)shareButtonPressed:(id)sender
{
if (facebook == nil)
{
// Setup Facebook connection
[self setUpFacebookConnection];
}
}
- (void)setUpFacebookConnection
{
facebook = [[Facebook alloc] initWithAppId:#"xxxxxx" andDelegate:self];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"])
{
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid])
{
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_actions",
nil];
[facebook authorize:permissions];
}
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
- (void)fbDidLogin
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
When I run this code and press the button it opens up safari with a page allowing the user to choose whether to allow the app access to Facebook. Once you accept this it switched back to my app, however the method fbDidLogin never gets called so I can't ever post any messages.
Please can someone help me out, I've spent ages trawling the internet for advice but all of the relevant articles are either outdated or they have the connection to Facebook setup in the app delegate class. Whereas in my situation I only want to user to connect when they choose (i.e. when they press the button).
This method:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [facebook handleOpenURL:url];
}
must be placed in your application delegate. You will have to change the reference to the facebook instance so that it's valid in the app delegate, of course.
I know that this question has been asked, but I have been reading through threads all day and have applied all of the fixes I could find and am still having an issue.
I am trying to implement Facebook SDK's new SSO feature to allow my app to authenticate with Facebook's app instead of a webView. When my app switches to Facebook's app, it says loading for a few seconds and switches back but the token is still null. I have a feeling it has to do with the URL scheme for my app but I have followed many tutorials and am fairly confident that my current plist values are correct:
Here is the code I have implemented in my appDelegate and viewController files:
appDelegate.h
Facebook *facebook;
appDelegate.m
// Pre 4.2 support
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
// For 4.2+ support
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [facebook handleOpenURL:url];
}
SecondViewController.m
-(IBAction) fbButton {
//FACEBOOK INTEGRATION
appDelegate.facebook = [[Facebook alloc] initWithAppId:#"222087841143437" andDelegate:appDelegate];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
appDelegate.facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
appDelegate.facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![appDelegate.facebook isSessionValid]) {
appDelegate.facebook.sessionDelegate = self;
[appDelegate.facebook authorize:permissions];
NSLog(#"Token: %#", [defaults objectForKey:#"FBAccessTokenKey"]);
} else {
NSLog(#"Already logged in!");
}
[appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
NSString *nameID = [[NSString alloc] initWithFormat:#"%# (%#)", [result objectForKey:#"name"], [result objectForKey:#"id"]];
NSMutableArray *userData = [[NSMutableArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
[result objectForKey:#"id"], #"id",
nameID, #"name",
[result objectForKey:#"picture"], #"details",
nil], nil];
[userData release];
[nameID release];
NSLog(#"DATA RECEIVED: %#", result);
}
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(#"request:didReceiveResponse:");
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
NSLog(#"%#", [error localizedDescription]);
NSLog(#"Err details: %#", [error description]);
};
- (void)fbDidLogin {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[[appDelegate facebook] accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[[appDelegate facebook] expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
NSLog(#"Facebook Logged in!");
[appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self];
}
I know that I call [appDelegate.facebook requestWithGraphPath:#"me" andDelegate:self] twice, but I don't think that's the problem.
Here is a snippet from the console when I press the login button:
2011-10-18 15:37:33.287 Track[2235:707] Token: (null)
2011-10-18 15:37:36.578 Track[2235:707] request:didReceiveResponse:
2011-10-18 15:37:36.584 Track[2235:707] The operation couldn’t be completed. (facebookErrDomain error 10000.)
2011-10-18 15:37:36.586 Track[2235:707] Err details: Error Domain=facebookErrDomain Code=10000 "The operation couldn’t be completed. (facebookErrDomain error 10000.)" UserInfo=0x1ce480 {error=<CFBasicHash 0x1c9560 [0x3e368630]>{type = mutable dict, count = 2,
entries =>
2 : <CFString 0x19a830 [0x3e368630]>{contents = "type"} = <CFString 0x11d230 [0x3e368630]>{contents = "OAuthException"}
3 : <CFString 0x1f5b60 [0x3e368630]>{contents = "message"} = <CFString 0x1f8a70 [0x3e368630]>{contents = "An active access token must be used to query information about the current user."}
I appreciate the help and I really hope I didn't miss a discussion on here that solves this problem. Here are a few (of the many) that I have read through and had no success in finding a solution
How to implement Single Sign On (SSO) using facebook ios sdk for iphone
Facebook SSO and request iOS SDK
Facebook API for iPhone Error: An active access token must be used
Make sure that your Facebook application (the actual application that you created on Facebook) is not in sandbox mode and if it is make sure that the user your Facebook application (the iPhone Facebook client) is currently logged in with is a developer for that application.
I am making an application where I need to invoke requests in multiple view controllers. I don't want the Facebook log in screen to show when the app is launched. It should only open when the user taps a button in another view controller if the user is not logged in, so putting the code in app delegate is not working solution to the problem. And the whole asynchronous process of requesting data in the Facebook API is killing me, I am starting to loose hair.
A class with static methods to get the facebook object and treat it as a singleton.
#import "PBSocialMedia.h"
#import "PBFacebookDelegate.h"
static Facebook *facebook;
static PBFacebookDelegate *facebookDelegate;
#implementation PBSocialMedia
+ (Facebook *)sharedFacebook {
if (facebook == nil) {
facebookDelegate = [[PBFacebookDelegate alloc] init];
facebook = [[Facebook alloc] initWithAppId:#"156687441079334" andDelegate:facebookDelegate];
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
NSArray *permissions = [NSArray arrayWithObjects:#"user_photo_video_tags", #"friends_photo_video_tags", #"user_photos", #"friends_photos", nil];
if (![facebook isSessionValid]) {
[facebook authorize:permissions];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:#"connectedToFacebook" object:self];
}
return facebook;
}
+ (Facebook *)sharedFacebookWithoutAuthorizing {
return facebook;
}
#end
A class that implements the Facebook session delegate used in the class above
#import "PBFacebookDelegate.h"
#import "PBSocialMedia.h"
#implementation PBFacebookDelegate
/**
* Called when the user successfully logged in.
*/
- (void)fbDidLogin {
Facebook *facebook = [PBSocialMedia sharedFacebook];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"connectedToFacebook" object:self];
}
/**
* Called when the user dismissed the dialog without logging in.
*/
- (void)fbDidNotLogin:(BOOL)cancelled {
[[NSNotificationCenter defaultCenter] postNotificationName:#"dismissedFacebookDialog" object:self];
}
/**
* Called when the user logged out.
*/
- (void)fbDidLogout {
[[NSNotificationCenter defaultCenter] postNotificationName:#"disconnectedFromFacebook" object:self];
}
#end
As you see from the two classes above I am making use of notifications so that I know when the user logs in/out of Facebook. The code below is an example of how I am trying to use it:
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
if (self.canUseGraphAPI) {
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
NSLog(#"Can use");
} else {
NSLog(#"Can't use");
}
}
- (void)connectedToFacebook {
self.canUseGraphAPI = YES;
}
- (void)disconnectedFromFacebook {
self.canUseGraphAPI = NO;
}
This is ofcourse NOT working as intended because of the stupid asynchronous request. It will work correct only when the user is logged in. So the first time I open the app it invokes the [PBSocialMedia sharedFacebook]; Then it proceed with the request function AND NOT waiting for the sharedFacebook function to finish. I really hope somebody has encountered this problem before. I want to do requests in different places in my code, but only when the user is logged in, and it need to WAIT while the user logs in before requesting. The code below is not working but it shows what I want!
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
while (self.canUseGraphAPI) {
// WAITING FOR LOGIN IN
}
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
}
- (void)connectedToFacebook {
self.canUseGraphAPI = YES;
}
- (void)disconnectedFromFacebook {
self.canUseGraphAPI = NO;
}
I would start restructuring your code to work by passing in blocks that you want executed upon getting your answer back from FB. This is similar to how you do ajax in JQuery.
- (void)viewDidLoad {
[super viewDidLoad];
Facebook *facebook = [PBSocialMedia sharedFacebook];
[self withGraphAPIDo: ^{
[facebook requestWithGraphPath:#"106378916135129/photos" andDelegate:self];
}];
}
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.