facebook-ios-sdk logout - iphone

I am building a basic app for school that gets some info from facebook using the facebook-ios-sdk. However, when I log out of the app, it does not give me the option to log back in, even in the demo from facebook. I am checking to see if the sessions is still valid, and it always comes out invalid. That is another problem. Here is the code I have. Any help is appreciated.
- (void)viewDidLoad {
_facebook = [[Facebook alloc] init];
if ([_facebook isSessionValid] == NO) {
//show proper buttons for login
loginButton.hidden = NO;
logoutButton.hidden = YES;
}
else {
//show proper buttons for logout
loginButton.hidden = YES;
logoutButton.hidden = NO;
}
}
That is to check whether I am logged in or not. Then I have the proper buttons showing, but the code above is always returning that the session is invalid. Here are the functions I call to log in or out:
- (void)login {
[_facebook authorize:kAppId permissions:_permissions delegate:self];
}
/**
* Invalidate the access token and clear the cookie.
*/
- (void)logout {
[_facebook logout:self];
}

The facebook object says it has no valid session because its accessToken and/or expirationDate are nil. That's probably because it doesn't persist them itself. You probably need to record the accessToken and expirationDate by handling the login in an FBSessionDelegate's fbDidLogin method.
- (void)fbDidLogin {
[[NSUserDefaults standardUserDefaults] setValue: _facebook.accessToken forKey: #"access_token"];
[[NSUserDefaults standardUserDefaults] setValue: _facebook.expirationDate forKey: #"expiration_date"];
}
Use NSUserDefaults, for example, to persist those values to the device. Then, every time you alloc and init your _facebook object, immediately set the accessToken and expirationDate to the values you stored in NSUserDefaults.
That should fix the facebook object saying isSessionValid = NO always. As for the other problem, I have the same one :(

Related

Iphone app facebook connection?

hello i have a app that connects and post to user wall but when i try to post it always open the persmission page and in that page it writes you already give permission to this app.I want it to come only 1 time can anyone help me to do that?
- (id)init {
if (self == [super init]) {
facebook = [[Facebook alloc] initWithAppId:kAppId];
facebook.sessionDelegate = self;
if(permissions==nil){
permissions = [[NSArray arrayWithObjects:
#"read_stream", #"user_birthday",
#"publish_stream", nil] retain];
}
[self login];
}
return self;
}
- (void)login {
if (![_session isConnected]) {
[self postToWall];
}
// only authorize if the access token isn't valid
// if it *is* valid, no need to authenticate. just move on
if (![facebook isSessionValid]) {
[facebook authorize:permissions delegate:self];
}
is it because i init method?
See this page - https://developers.facebook.com/docs/guides/mobile/. Basically what you want to do is save the authentication information (access_token) when the user is authorized, then next time you can check for the saved values and skip the authentication.

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.

facebook connect not working

This all is driving me nuts.
I just integrated facebook in my iphone app.
After typing in my username and password in the login dialog this method is called.
- (void)request:(FBRequest*)request didLoad:(id)result {
if ([request.method isEqualToString:#"facebook.fql.query"]) {
NSLog(#"result %#",result);
NSArray* users = result;
NSLog(#"users %#",users);
NSDictionary* user = [users objectAtIndex:0];
NSString* name = [user objectForKey:#"name"];
self.facebookName = name;
if (_posting) {
[self postToWall];
_posting = NO;
}
}
}
But after this the app crashes most of the times and when I tried to log the "result" array it appears to be empty. Why is it so?
What should I do? Please suggest.
use this code
NSArray *users=[[NSArray alloc]initWithObjects:result, nil];
NSLog(#"users %#",users);
NSDictionary* user = [[NSDictionary alloc]initWithObjectsAndKeys:users,#"users", nil];
NSLog(#"%#",user);
I got the reason for this.
This was due to the session getting lost frequently in between.
So I had to call [session resume] in the facebook login action event
and in this manner if at all the session is lost by any chance then the previous session is resumed and the "result" does not appears to be nil in (void)request:(FBRequest*)request didLoad:(id)result method.
Hope this helps out those who are stuck in the same issue.

facebook iOS sdk custom delegate and SSO authorization

I've been toying with the new facebook iOS sdk. I have gotten my project to the point where someone can login successfully. However I have 2 questions:
1) to hit the graph api you issue the following call: [facebookInstance requestWIthGraphPath:#"me" andDelegate:self]. Is it possible to specificy a delegate other than self? Currently all responses go to the (void)request: (FBRequest *) request didLOad:(id) result. But since my app may issue requests to the facebook api at different times and need different things to happen for each respective request issued, how can I specifiy which callback function the response should hit in my app? Is this possible?
2) Once the user has logged in, how can you check their authorization/login status so that I can disable the login button if they are already logged in? Consider the example of a user turning on the app for the 1st time and logging in. Then closing the app, and opening a few minutes later. I rather not show the user the login button the 2nd time and instead start pulling information to display such as their name.
1) There shouldn't be anything wrong with specifying a delegate other than self, as long as the object you provide as the delegate conforms to the FBRequestDelegate protocol. Alternately you can interrogate the FBRequest object you get in the delegate method to determine which request it was that just loaded and what the appropriate response is.
2) To make it so the user stays logged in, you need to save the accessToken (an NSString) and the expirationDate (an NSDate) properties of the Facebook object when the user logs in. Then, when you would log your user in, attempt to restore these values.
Some code snippets that may help:
- (void)fbDidLogin
{
NSString *tokenString = [[self facebook] accessToken];
NSDate * expirationDate = [[self facebook] expirationDate];
[[NSUserDefaults standardUserDefaults] setObject: tokenString forKey:#"FacebookToken"];
[[NSUserDefaults standardUserDefaults] setObject: expirationDate forKey:#"FacebookExpirationDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
And, when you need to log the user in:
NSString *tokenString = [[NSUserDefaults standardUserDefaults] objectForKey:#"FacebookToken"];
NSDate *expDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"FacebookExpirationDate"];
if (tokenString != nil && expDate != nil)
{
[facebook setAccessToken:tokenString];
[facebook setExpirationDate:expDate];
}
if ([facebook isSessionValid])
{
//Your session is valid, do whatever you want.
}
else
{
//Your session is invalid
//(either the session is past the expiration date or there is no saved data for the login)
//you need to ask the user to log in
}

To display permission page in facebook of iphone

I am new to iphone development, i want to display the permission page after logging facebook.
buttonIndex is the index of my actionsheets.
if(buttonIndex == 1)
{
session = [FBSession sessionForApplication:#"My App key" secret:#"My Key" delegate:self];
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:session] autorelease];
[dialog show];
}
by using those code successfully loggin to facebook, but i want to permission page to display,
so i can use,
- (void)session:(FBSession*)session didLogin:(FBUID)uid
{
NSLog(#"User with id %lld logged in.", uid);
FBPermissionDialog* dialog1 = [[[FBPermissionDialog alloc] init] autorelease];
dialog1.delegate = self;
dialog1.permission = #"uid";
[dialog1 show];
}
But its not working. Where can i put that code.
And I want to share my content after the permission allowed.
If i logout the facebook, it goes to the browser but i want to return my application after logout,
Please help me out, guide me plz.
I would change this dialog1.permission = #"uid"; to something like this
dialog1.permission = #"publish_stream";. Because you want to publish your content to the users stream, right?
- (void)session:(FBSession*)session didLogin:(FBUID)uid
After loggin in I would first check if you might already have the permission to publish to the user's stream, by creating a FBRequest
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: #"publish_stream", #"ext_perm", nil];
[[FBRequest requestWithDelegate:self] call:#"facebook.users.hasAppPermission" params:params];
The result you can evaluate here
- (void)request:(FBRequest*)request didLoad:(id)result
e.g. like this
if ([request.method isEqualToString:#"facebook.users.hasAppPermission"])
{
NSString *success = result;
if ([success isEqualToString:#"1"])
{
NSLog(#"User has app permission");
// publish content now
...
}
else
{ // else ask for permission, opening permission dialog
...
}
I highly recommend this guy's tutorial, Brandon Treb, on integrating Facebook. He does a very thorough presentation and takes you line-by-line, so if it does not work, its a typo on your part. His tutorial got me up and running in less than two hours.
http://brandontreb.com/