5
votes

I'm adding FBLoginView to my ViewController < FBLoginViewDelegate >:

FBLoginView *loginview = [[FBLoginView alloc] init];    
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;    
[self.view addSubview:loginview];    
[loginview sizeToFit];

All the necessary fields in plist (FacebookAppID, FacebookDisplayName, URL Schemes) are all set according to the tutorial. The facebook app is also configured according to the tutorial (bundle ID is set, Facebook login is enabled).


But the login still isn't performed. When I press on "log in", I get redirected to the browser with facebook login, but when it's finished, I'm not logged in the app (loginViewFetchedUserInfo:user: isn't called, "log in" hasn't changed to "log out"). What can be the problem?

4

4 Answers

2
votes

Everything worked after I implemented the following in the AppDelegate.m (taken from one of the official examples):

- (void)sessionStateChanged:(FBSession *)session
                      state:(FBSessionState) state
                      error:(NSError *)error
{
    switch (state) {
        case FBSessionStateOpen:
            if (!error) {
                // We have a valid session
                //NSLog(@"User session found");
                [FBRequestConnection
                 startForMeWithCompletionHandler:^(FBRequestConnection *connection,
                                                   NSDictionary<FBGraphUser> *user,
                                                   NSError *error) {
                     if (!error) {
                         self.loggedInUserID = user.id;
                         self.loggedInSession = FBSession.activeSession;
                     }
                 }];
            }
            break;
        case FBSessionStateClosed:
        case FBSessionStateClosedLoginFailed:
            [FBSession.activeSession closeAndClearTokenInformation];
            break;
        default:
            break;
    }

    [[NSNotificationCenter defaultCenter]
     postNotificationName:FBSessionStateChangedNotification
     object:session];

    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Error"
                                  message:error.localizedDescription
                                  delegate:nil
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
        [alertView show];
    }
}

/*
 * Opens a Facebook session and optionally shows the login UX.
 */
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
    return [FBSession openActiveSessionWithReadPermissions:nil
                                              allowLoginUI:allowLoginUI
                                         completionHandler:^(FBSession *session,
                                                             FBSessionState state,
                                                             NSError *error) {
                                             [self sessionStateChanged:session
                                                                 state:state
                                                                 error:error];
                                         }];
}

/*
 *
 */
- (void) closeSession {
    [FBSession.activeSession closeAndClearTokenInformation];
}

/*
 * If we have a valid session at the time of openURL call, we handle
 * Facebook transitions by passing the url argument to handleOpenURL
 */
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    // attempt to extract a token from the url
    return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
}
2
votes

You need to add the following to the app delegate

- (BOOL)application:(UIApplication *)application
        openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
     annotation:(id)annotation {

  // Call FBAppCall's handleOpenURL:sourceApplication to handle Facebook app responses
  BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];

  // You can add your app-specific url handling code here if needed

  return wasHandled;
}
0
votes

You may need to implement the

(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url method

Be sure to call:

return [FBSession.activeSession handleOpenURL:url];

When applicable.

0
votes

@Sergey: Are you want to open FBDialog on your native app or in browser? If you to want open in your native app then use "FBSessionLoginBehaviorForcingWebView". Here is my code that I am using:

NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];

FBSession *session = [[FBSession alloc] initWithPermissions:permission];

[FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];

[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {

    switch (status) {
        case FBSessionStateOpen:
            [self  yourmethod];
            break;
        case FBSessionStateClosedLoginFailed: {
            // prefer to keep decls near to their use
            // unpack the error code and reason in order to compute cancel bool
            NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
            NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
            BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
            if(error.code == 2) {
                UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:@"FBAlertTitle"
                                                                       message:@"FBAuthenticationErrorMessage"
                                                                      delegate:nil
                                                             cancelButtonTitle:@"Ok"
                                                             otherButtonTitles:nil];
                [errorMessage performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];
                errorMessage = nil;
            }
        }
            break;
            // presently extension, log-out and invalidation are being implemented in the Facebook class
        default:
            break; // so we do nothing in response to those state transitions
    }
}];
permission = nil;

or you want to open in browser then use following :

In your .h file 

#import <FacebookSDK/FacebookSDK.h>  and add FBLoginViewDelegate  delegate

In you .m file  
     FBLoginView *loginview = [[FBLoginView alloc] init];
     loginview.frame = CGRectOffset(loginview.frame, 5, 5);
     loginview.delegate = self;
     [self.view addSubview:loginview];
     [loginview sizeToFit];

// use following delegate methods

- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
    // first get the buttons set for login mode
}

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
                            user:(id<FBGraphUser>)user {
    // here we use helper properties of FBGraphUser to dot-through to first_name and
    // id properties of the json response from the server; alternatively we could use
    // NSDictionary methods such as objectForKey to get values from the my json object
    NSLog(@"userprofile:%@",user);
}
- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {
    //BOOL canShareAnyhow = [FBNativeDialogs canPresentShareDialogWithSession:nil];

}

- (void)loginView:(FBLoginView *)loginView handleError:(NSError *)error {
    // see https://developers.facebook.com/docs/reference/api/errors/ for general guidance on error handling for Facebook API
    // our policy here is to let the login view handle errors, but to log the results
    NSLog(@"FBLoginView encountered an error=%@", error);
}