Signing in with Facebook - FBSession questions - ios

I've been trying to integrate Facebook and came across some issues and questions.
1.
I have implemented the following method in viewDidLoad:
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:NO completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
When there's a token cached, the block is executed as expected.
But, when there isn't a token cached, the block isn't executed at all.
Is this a normal behaviour? If so, when is the block executed?
2.
I've been said that access tokens are expired at some point.
Should I be worried about what to do when a token is expired, or Facebook handles it automatically?
3.
What FBSession actually means?
As I understand - the FBSession manages the token and the user authentication,
Yet, I don't understand what does it mean to "open a session" or what the FBSessionStates represent.
When is the FBSession created? Right when the app loads?
4.
I've found that graph that should explain the FBSessionsStates:
After reading the graph, I still don't understand the flow - when are FBSessionStateCreated & FBSessionStateCreatedTokenLoaded the current state of the session?
As you can see, I have many questions about the whole process.
I've tried to organize the questions in a way that other people seeing this in the future, won't be having the struggles I'm having.
Thank you.

Related

Facebook iOS SDK: requestNewPublishPermissions not initializes permissions

I just started using facebook sdk and slightly confused with it documentation. It's well written, but very often does not correspond to current SDK version. So i'm not found what to do with this situation:
I request publish permissions when firstly require them, with the next code:
[[FBSession activeSession] requestNewPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (error) {
NSLog(#"Permissions request error: %#", error.description);
}
completion(error == nil);
}];
I need only one publish permission - 'publish_actions', when i request it sdk redirects me to facebook app and immediately returns back to the my app without asking whether i'm agree to give this permission.
There are no errors in completionHandler, but through debug i found that this permission was saved in the variable _requestedReauthPermissions:
So, finally, permission i requested not granted to me.
How properly request publish permission? What could I miss? May it occur due to setup of facebook app?

How is FBSession used

I'm integrating facebook and I still don't see how the FBSession ties everything together.
This is how I think it works.
You need a new FBSession each app launch. (Is this true?). The FBSession also needs to be closed every time the app stops (if this is true, how do we start a new session without asking user to login again?)
As far as the session is concerned, [FBSession activeSession] is a global managed by the facebook sdk? Should we just use this as the default session anytime we want to pull data or check if a session is alive?
Assuming the above logic has worked out and you get the user id (fb id) then we feed that id to a FBImageView and we get a profile pic, but isn't this id changing every launch? So storing it on our server isn't helpful? Should we get the id every launch?
Please let me know what is right or wrong about the above statements, and an explanation of why?
Thank you.
I suggest you to use activeSession of FBSession. This way you don't have to create sessions yourself. Just use [FBSession openActiveSessionWithReadPermissions:...] method of FBSession for activating activeSession, and on successful opening, You could use FBSession.activeSession for your Facebook requests. Good luck!
PS>
In order to restore activeSession you can do:
if (![FBSession.activeSession isOpen]) {
[FBSession openActiveSessionWithReadPermissions:#[#"basic_info"] allowLoginUI:NO completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
}];
}
which will open the session if it has cached token information without showing login UI.

read and publish permission in facebook sdk 3.0 iOS

In the last SDK, read and publish permissions are separated. So, in my code, whenever the users logs in I am using this code:
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:
^(FBSession *session,
FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
I have seen in the facebook developer that when I want to publish, I should ask for publish permissions like this:
// can include any of the "publish" or "manage" permissions
NSArray *permissions =
[NSArray arrayWithObjects:#"publish_actions", nil];
[[FBSession activeSession] reauthorizeWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
/* handle success + failure in block */
}];
Since this is my first app that I am using facebook integration, I want to ask a couple of things:
1) Can these sessions be open at the same time? I will ask for the publish permissions only when the user wants to publish, but should I do something else with the other session? Like close it first, and reopen it later or I should not worry about?
2) If I have a postToFriends button for example, my pseudocode for making it work would be like this, right?
- (IBAction)postToFriendaction:(id)sender {
if (!FBSession.activeSession.isOpen) {
/* code from the above for enabling publish permissions*/
}
or I should change !FBSession.activeSession.isOpen to something else, because no the user is logged in with read permission only, he never enters the if clause. Can you help me?
The two sessions you refer to are actually the same session (it's the "active" session that's statically available after a call to openActiveSession... is called). So you don't need to do anything with the other session.
You should have a look at either the Scrumptious or Hello Facebook sample apps that ship with the SDK. They both give examples on how to post (while asking for publish permissions).

FBSession requestNewPublishPermissions fails before response

I'm trying to get post permissions from a user using the Facebook SDK on iOS.
I'm calling the code below in a method that is called if the app does not have the required publishing permissions to post to the users facebook wall.
// No permissions found in session, ask for it
[FBSession.activeSession requestNewPublishPermissions: [NSArray arrayWithObject:#"publish_actions"]
defaultAudience: FBSessionDefaultAudienceEveryone
completionHandler: ^(FBSession *session, NSError *error)
{
if( !error )
{
// Do something
}
}];
The first time I call this code it takes the user to the permissions page, and before it even switches to safari on the device the block gets called and this error message is returned
Error Domain=com.facebook.sdk Code=2 "The operation couldn’t be completed. (com.facebook.sdk error 2.)" UserInfo=0xc426410 {com.facebook.sdk:ErrorLoginFailedReason=com.facebook.sdk:ErrorReauthorizeFailedReasonUserCancelled,
The app then continues on to show the permissions page in safari where the user selects ok. Then it returns to the app. Permissions have not been set at this point even tho the user was presented with the permissions page and accepted.
When trying to post a second time it takes the user to the permissions page in safari and the requestNewPublishPermissions method doesn't fail instantly. The user selects ok and then everything works as expected.
So it is only on the very first time calling requestNewPublishPermissions that it fails instantly returning the error ErrorReauthorizeFailedReasonUserCancelled.
This happens in the simulator and on the device.
Any idea what might be causing this?
I found the solution to this problem on the answer to this question Facebook iOS 3.1 sdk login with publish permission callbacks
dispatch_async(dispatch_get_current_queue(), ^{
[self openSessionForPublishPermissions];
});
Where opensessionforpublishpermissions is the method that contains the requestNewPublishPermissions method.
"The reason is that the call to reauthorize.. needs to be after the event loop of which openActiveSession.. is called."
I assume this is a bug in the Facebook SDK, it doesn't make sense for this to be normal behaviour and I haven't seen any of the Facebook docs comment on this being the expected behaviour.
I had the similar issue, and the answer, provided by Tiddly worked for me. For some time.
Later I ran across the same issue. I don't know why, may be it was concerned with SDK or iOS updates, may be run loop of the app became more complicated. So I inspected FB SDK source and figured out that this issue occurs when you ask publish permissions just after read permissions, like this:
// Open with read permissions
[FBSession openActiveSessionWithReadPermissions: readPermissions
allowLoginUI: YES
completionHandler: ^
(FBSession *session, FBSessionState status, NSError *error)
{
// Ask for publish permissions (This is incorrect!)
[FBSession.activeSession requestNewPublishPermissions:publishPermissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:
^(FBSession *session, NSError *error)
{
// ...
}];
}];
When your app switches to Safari or FacebookApp and back,
-application: openURL: sourceApplication: annotation:
is called. CompletionHandler of
+openActiveSessionWithReadPermissions:
called immediately after this, before
applicationDidBecomeActive:. And after you start reauthorisation
applicationDidBecomeActive: is finally called. So, FB SDK think that user has returned back to the app, without giving permissions and reauthorisation fails with that "com.facebook.sdk error 2." error.
Sometimes dispatch_async() works well. But the robust solution, is to wait for active session to handle App Did Become Active event. And then request additional publish permissions. Here is an example of how to achieve this:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[FBAppCall handleDidBecomeActive];
if (self.shouldReauthorise) {
[self requestPublishPermissions];
self.shouldReauthorise = NO;
}
}

Cannot send facebook apprequest from iOS because FBSession.activeSession.isOpen gives false

my app can only send app request during the first run that the user logins into facebook. Once the app is restarted, the app request gets stopped because FBSession.activeSession.isOpen gives false.
Although, FBSession.activeSession.isOpen gives false still the app can perform other operations such as posting to the wall, getting friend list etc. Only it cannot send app requests. And still it has a valid access token too.
Any ideas?
You say "FBSession.activeSession.isOpen gives false", but, just to be sure : when do you run this test? When your call to the login request returns, or inside the asynchronous request's callback ?
If it's done outside the request's callback, it may say that the session is not opened yet. Then, the request returns properly, which means that any further call to another FB request succeeds.
Does that help?
If it does not, maybe an overview of your code could.
Ok, next to your comment from the previous answer :
yes, that's what you said already. but WHERE in your code do you check isOpen? To expect a proper value, it should be something like this :
FBSession openActiveSessionWithReadPermissions:_readPerms allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
// here is the proper place to check the isOpen boolean, and to go on with your program, including the app request
}];
// not the proper place to check isOpen.
Does that help?

Resources