简体   繁体   English

Facebook SDK 3.1 iOS:如果用户从Facebook设置中删除应用,则处理登录

[英]Facebook SDK 3.1 iOS: Handle login if user remove app from Facebook Settings

I want to put some Facebook integration in my app. 我想在我的应用程序中添加一些Facebook集成。 At this point I've managed to login, post to friends wall, retrieve the list of friends, etc. Everything is OK except for one thing... 在这一点上,我已经成功登录,发布到朋友墙,检索朋友列表等。除了一件事之外,其他一切都还可以。

If the user removes the app from your Facebook settings / Applications and then enters to the iOS app, the code doesn't recognize that the Facebook app was removed from the user settings and assumes that is logged in (this is the problem because if the user tries to post to a friend's wall, the app do nothing). 如果用户从您的Facebook设置/应用程序中删除了该应用程序 ,然后输入iOS应用程序,则该代码无法识别该Facebook应用程序已从用户设置中删除,并假定已登录(这是因为如果用户尝试将其发布到朋友的墙上,则该应用不执行任何操作)。

Then, the user closes the iOS app and relaunches it... With this relaunch, the iOS app "is fixed" and detects that the user is no longer logged in. 然后,用户关闭iOS应用并重新启动...通过重新启动,iOS应用“已修复”并检测到用户不再登录。

I can't manage to detect the moment right after the user deletes the facebook app from the settings in order to bring the login flow to the user... 为了将登录流程带给用户,我无法设法检测到用户从设置中删除Facebook应用之后的那一刻...

Here is my code: 这是我的代码:

At first scene of my app... 在我的应用的第一个场景中...

if([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded)
{
    NSLog(@"Logged in to Facebook");
    [self openFacebookSession];
    UIAlertView *alertDialog;

    alertDialog = [[UIAlertView alloc] initWithTitle:@"Facebook" message:@"You're already logged in to Facebook" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];

    [alertDialog show];

    [alertDialog release];
    return YES;
}
else{
    NSLog(@"Not logged in to Facebook"); //Show the login flow
    return NO;
}

Here is the code for openFacebookSession 这是openFacebookSession的代码

-(void)openFacebookSession
{
    NSArray *permissions = [[NSArray alloc] initWithObjects:
                            @"publish_stream",
                            nil];

    [FBSession openActiveSessionWithPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
        [self sessionStateChanged:session state:status error:error];
    }];
}

Code for sessionStateChanged... sessionStateChanged的代码...

-(void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error
{
    switch (state) {
        case FBSessionStateOpen: {
            NSLog(@"Session opened");
        }
            break;
        case FBSessionStateClosed:
        case FBSessionStateClosedLoginFailed:
            [FBSession.activeSession closeAndClearTokenInformation];
            break;
        default:
            break;
    }

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

Thank you very much! 非常感谢你!

I found this happening to myself as well.... It was discovered when a user changed their facebook password, and we could no longer authenticate. 我也发现这也发生在我自己身上。...是在用户更改了Facebook密码后才发现的,我们无法再进行身份验证。 Doing a manual resync / clear of the account session allowed them to login again. 手动重新同步/清除帐户会话可以使他们再次登录。

-(void)syncFacebookAccount
 {
    [self forceLogout];
    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType *accountTypeFB = [accountStore         accountTypeWithAccountTypeIdentifier:@"com.apple.facebook"];
    if (accountStore && accountTypeFB) {
    NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
    id account;
    if (fbAccounts && [fbAccounts count] > 0 && (account = [fbAccounts objectAtIndex:0])) {
    [accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
                    // Not actually using the completion handler...
    }];
            }
        }
    }

It's actually VERY hard to parse out and detect these types of errors for two reasons: 实际上,解析和检测这些类型的错误非常困难,原因有两个:

  1. I cannot figure out any way to detect this problem until you actually attempt and fail an FBRequest (or similar), and 在您实际尝试并失败FBRequest(或类似请求)之前,我无法找出任何方法来检测此问题,并且
  2. The NSError object passed from the failed FBRequest is ABSURDLY difficult to parse and use in any functional way. 从失败的FBRequest传递的NSError对象很难以任何功能方式解析和使用。

Below is the crazy method I wrote while literally pulling an all-nighter to deal with this. 下面是我写的一个疯狂方法,实际上是为了吸引一个通宵人员而写的。 It handles the NSError *error object from the failed FBRequest attempt, and passes it to the relevant methods OR displays the most sensible error I could find (or hits the bottom catch-all). 它处理来自失败的FBRequest尝试的NSError *error对象,并将其传递给相关方法,或者显示我可以找到的最明智的错误(或触及所有错误)。

Note the comments - particularly around innerError and parsedResponse - that detail what I've discovered so far. 请注意注释-特别是关于innerErrorparsedResponse的注释-详细说明了到目前为止我发现的内容。 Good luck, brave soldier: 祝你好运,勇敢的士兵:

- (void)handleFacebookError:(NSError *)error
         withPermissionType:(RMFacebookPermissionsType)type // this is just a typedef enum specifying Write or Read permissions so I can react accordingly
             withCompletion:(void (^)(BOOL retry))completionBlock {

    newMethodDebugLog;
    NSParameterAssert(error);
    NSParameterAssert(type);
    NSParameterAssert(completionBlock); //  the completion block tells the controller whether the error is 'fatal' or can be recovered - if YES, it can be recovered

    // this is the parsed result of the graph call; some errors can appear here, too, sadly
    NSDictionary *parsedResponse = [error.userInfo objectForKey:@"com.facebook.sdk:ParsedJSONResponseKey"];
    int parsedErrorCode = [[[[parsedResponse objectForKey:@"body"]
                             objectForKey:@"error"]
                            objectForKey:@"code"]
                           intValue];

    // this is an instance of NSError created by Facebook; it contains details about the error
    NSError *innerError = [error.userInfo objectForKey:@"com.facebook.sdk:ErrorInnerErrorKey"];

    // innerError is usually un-recoverable
    if (innerError) {

        // innerError seems to be the response given in true HTTP problems;
        DebugLog(@"______innerError FOUND______");
        DebugLog(@"innerError: %@",innerError);
        DebugLog(@"innerError.code: %d",innerError.code);

        // digging deep enough, you can actually find a coherent error message! :D
        DebugLog(@"innerError.localizedDescription: %@",innerError.localizedDescription);

        if (![alert isVisible]) {

            NSString *errorString = @"Facebook Connection Failed";

            NSString *okString = @"OK";

            alert = [[UIAlertView alloc] initWithTitle:errorString
                                               message:innerError.localizedDescription
                                              delegate:nil
                                     cancelButtonTitle:okString
                                     otherButtonTitles:nil];

            [alert show];

        } else {

            DebugLog(@"Alert already showing!");

        }

        completionBlock(NO);

    } else if (parsedResponse &&
               parsedErrorCode != 2) { // I honestly forget what error 2 is.. documentation fail :(

        // parsedResponses can usually be recovered
        DebugLog(@"parsed response values: %@",[parsedResponse allValues]);

        switch (parsedErrorCode) {
            case 2500:
            case 200:
            case 190:
            {
                DebugLog(@"parsedError code hit! forcing re-login.");

                // all errors in case 190 seem to be OAuth issues
                // http://fbdevwiki.com/wiki/Error_codes#Parameter_Errors
                // if needed, "error_subcode" 458 == user has de-authorized your app
                // case 2500 reported while grabbing from a photo album & not logged in
                // case 200 "requires extended permission: publish_actions"

                if (type == RMFacebookPermissionsTypeRead) {

                    [self _getFacebookReadPermissionsWithUI:YES
                                                 completion:completionBlock];

                } else if (type == RMFacebookPermissionsTypeWrite) {

                    [self _getFacebookWritePermissionsWithUI:YES
                                                  completion:completionBlock];

                }

                break;
            }

            default:
                completionBlock(YES);
                break;
        }

    } else {

        if (![alert isVisible]) {

            NSString *errorString = @"Facebook Error";

            NSString *messageString = @"Mixture Photos was unable to connect to Facebook on your behalf. This is usually a temporary problem. Please try again later.";

            NSString *okString = @"OK";

            alert = [[UIAlertView alloc] initWithTitle:errorString
                                               message:messageString
                                              delegate:nil
                                     cancelButtonTitle:okString
                                     otherButtonTitles:nil];

            [alert show];

        } else {

            DebugLog(@"Alert already showing!");

        }

        completionBlock(NO);

    }
}

I have the same problem and could not find proper documentation about error codes on Facebook SDK site. 我有同样的问题,在Facebook SDK网站上找不到有关错误代码的正确文档。

I solved problem by comparing the [error code]; 我通过比较[error code];解决了问题[error code]; or [error userInfo]; [error userInfo]; value. 值。

Your session will have the state FBSessionStateClosedLoginFailed and userInfo dictionary of error will have the following form 您的会话将具有状态FBSessionStateClosedLoginFailed并且userInfo错误字典将具有以下形式

"com.facebook.sdk:ErrorLoginFailedReason" = "com.facebook.sdk:ErrorLoginFailedReason";

On the other hand error code shows me 2 so that you can handle it at the end of sessionStateChanged::: function 另一方面,错误代码向我显示2以便您可以在sessionStateChanged :::函数的末尾进行处理

- (void)sessionStateChanged:(FBSession *)session
                  state:(FBSessionState)state
                  error:(NSError *)error {
switch (state) {
    case FBSessionStateOpen: {
        //update permissionsArrat
        [self retrieveUSerPermissions];

        if (!needstoReopenOldSession) {
            //First User information
            [self getUserInformation:nil];
        }

        NSNotification *authorizationNotification = [NSNotification notificationWithName:facebookAuthorizationNotification object:nil];
        [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification];

    }
    case FBSessionStateClosed: {
        break;
    }
    case FBSessionStateClosedLoginFailed: {
        [FBSession.activeSession closeAndClearTokenInformation];
        break;
    }
    default:
        break;
}

if (error) 
{
    NSNotification *authorizationNotification = [NSNotification  notificationWithName:faceBookErrorOccuredNotification object:error];
    [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification];
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM